Compare commits
81 Commits
develop
...
mochawesom
Author | SHA1 | Date |
---|---|---|
John McLear | 7630e71957 | |
John McLear | 28af41e906 | |
John McLear | 96520a3f31 | |
John McLear | b2f3828f5a | |
John McLear | 4ec538fc3c | |
John McLear | 6eb76a051d | |
John McLear | f999452df5 | |
John McLear | f280a6fc8a | |
John McLear | 48e910be1f | |
John McLear | 74909a2c7e | |
John McLear | 5d76206b93 | |
John McLear | f6413c8e39 | |
John McLear | 14db2e52c2 | |
John McLear | a908bbee8e | |
John McLear | 1dc4a2acf5 | |
John McLear | 843dd927ce | |
John McLear | 7f384f13cd | |
John McLear | 3718767d5a | |
John McLear | df580ec513 | |
John McLear | da237547ac | |
John McLear | 938f33f44d | |
John McLear | 704b9f94a6 | |
John McLear | d01aafb98c | |
John McLear | 3caedd370e | |
John McLear | f99d294a1c | |
John McLear | 71dd0bfa04 | |
John McLear | 360f32aa13 | |
John McLear | 88d56168c0 | |
John McLear | 05fe4904ed | |
John McLear | e8e90ac207 | |
John McLear | 189786979f | |
John McLear | c43de8ea59 | |
John McLear | ac420f4683 | |
John McLear | 5aa0ad3f55 | |
John McLear | ae49fcf1ae | |
John McLear | d12dbc7f63 | |
John McLear | fd7a7b4c6c | |
John McLear | 6f364b065d | |
John McLear | 3d69773cd2 | |
John McLear | e5d80a0696 | |
John McLear | 8fff1db4d0 | |
John McLear | 02bb5a5b73 | |
John McLear | f4eeb59b86 | |
John McLear | 103e3398ad | |
John McLear | ff71e41812 | |
John McLear | 28617ee9d0 | |
John McLear | 7696ec0a02 | |
John McLear | 96d9a40b04 | |
John McLear | 0c9a19bd1b | |
John McLear | 14c2987afc | |
John McLear | 4c825d3060 | |
John McLear | 55ac85473c | |
John McLear | 5d276944a8 | |
John McLear | 21736122a0 | |
John McLear | 2816820785 | |
John McLear | 928f1ef8ce | |
John McLear | 53708e69eb | |
John McLear | a6406663f4 | |
John McLear | 929859042c | |
John McLear | 01ac40dc56 | |
John McLear | 88d99c0d60 | |
John McLear | edf1dabe65 | |
John McLear | 809670dbea | |
John McLear | 986894f776 | |
John McLear | ff708c7160 | |
John McLear | d8ec9309d5 | |
John McLear | f6285e10e0 | |
John McLear | d74782c7e6 | |
John McLear | f2b54af6a4 | |
John McLear | b12becb6fb | |
John McLear | f3677feba1 | |
John McLear | 1b74f29f7b | |
John McLear | 45d54ca874 | |
John McLear | 48ebc3af5a | |
John McLear | 49ebba4d6c | |
John McLear | 6a93c66de4 | |
John McLear | 697bfd979b | |
John McLear | f37a95cad8 | |
John McLear | 35b01230d0 | |
John McLear | a3da6fefbd | |
John McLear | 5106002c62 |
|
@ -3,8 +3,8 @@ name: "Frontend tests"
|
|||
on: [push]
|
||||
|
||||
jobs:
|
||||
withoutplugins:
|
||||
name: without plugins
|
||||
withoutpluginsAndWithoutMinificationAndMaxAge0:
|
||||
name: without plugins and without minification
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
@ -19,6 +19,54 @@ jobs:
|
|||
TRAVIS_JOB_NUMBER: ${{ github.run_id }}-${{ github.run_number }}-${{ github.job }}
|
||||
run: tests/frontend/travis/sauce_tunnel.sh
|
||||
|
||||
- name: Install ep_preformance_test_hook
|
||||
run: npm install ep_performance_test_hooks
|
||||
|
||||
- name: Install all dependencies and symlink for ep_etherpad-lite
|
||||
run: bin/installDeps.sh
|
||||
|
||||
- name: export GIT_HASH to env
|
||||
id: environment
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short ${{ github.sha }})"
|
||||
|
||||
- name: Write custom settings.json with loglevel WARN
|
||||
run: "sed 's/\"loglevel\": \"INFO\",/\"loglevel\": \"WARN\",/' < settings.json.template > settings.json"
|
||||
|
||||
- name: Set minify to false
|
||||
run: "sed -i 's/\"minify\": \"true\",/\"minify\": \"false\",/' settings.json"
|
||||
|
||||
- name: Set maxAge to 0
|
||||
run: "sed -i 's/\"maxAge\": \"21600\",/\"maxAge\": \"0\",/' settings.json"
|
||||
|
||||
- name: Run the frontend tests
|
||||
shell: bash
|
||||
env:
|
||||
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
TRAVIS_JOB_NUMBER: ${{ github.run_id }}-${{ github.run_number }}-${{ github.job }}
|
||||
GIT_HASH: ${{ steps.environment.outputs.sha_short }}
|
||||
run: |
|
||||
tests/frontend/travis/runner.sh
|
||||
|
||||
withoutpluginsAndWithMinification:
|
||||
name: without plugins and with minification
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Run sauce-connect-action
|
||||
shell: bash
|
||||
env:
|
||||
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
TRAVIS_JOB_NUMBER: ${{ github.run_id }}-${{ github.run_number }}-${{ github.job }}
|
||||
run: tests/frontend/travis/sauce_tunnel.sh
|
||||
|
||||
- name: Install ep_preformance_test_hook
|
||||
run: npm install ep_performance_test_hooks
|
||||
|
||||
- name: Install all dependencies and symlink for ep_etherpad-lite
|
||||
run: bin/installDeps.sh
|
||||
|
||||
|
@ -39,8 +87,8 @@ jobs:
|
|||
run: |
|
||||
tests/frontend/travis/runner.sh
|
||||
|
||||
withplugins:
|
||||
name: with plugins
|
||||
withpluginsAndWithMinification:
|
||||
name: with plugins and with minification
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
@ -70,6 +118,7 @@ jobs:
|
|||
ep_spellcheck
|
||||
ep_subscript_and_superscript
|
||||
ep_table_of_contents
|
||||
ep_performance_test_hooks
|
||||
|
||||
# This must be run after installing the plugins, otherwise npm will try to
|
||||
# hoist common dependencies by removing them from src/node_modules and
|
||||
|
|
|
@ -182,8 +182,15 @@ exports.restartServer = async () => {
|
|||
|
||||
app.use(cookieParser(settings.sessionKey, {}));
|
||||
|
||||
stats.gauge('expressConfigureDuration', () => expressConfigureDuration);
|
||||
const preExpressConfigure = Date.now();
|
||||
hooks.callAll('expressConfigure', {app});
|
||||
const expressConfigureDuration = Date.now() - preExpressConfigure;
|
||||
|
||||
stats.gauge('expressCreateServerDuration', () => expressCreateServerDuration);
|
||||
const preExpressCreateServer = Date.now();
|
||||
hooks.callAll('expressCreateServer', {app, server: exports.server});
|
||||
const expressCreateServerDuration = Date.now() - preExpressCreateServer;
|
||||
|
||||
await util.promisify(exports.server.listen).bind(exports.server)(settings.port, settings.ip);
|
||||
};
|
||||
|
|
|
@ -5,8 +5,11 @@ const plugins = require('../../../static/js/pluginfw/plugin_defs');
|
|||
const CachingMiddleware = require('../../utils/caching_middleware');
|
||||
const Yajsml = require('etherpad-yajsml');
|
||||
const _ = require('underscore');
|
||||
const stats = require('../../stats');
|
||||
|
||||
exports.expressCreateServer = (hookName, args, cb) => {
|
||||
stats.gauge('minificationDuration', () => minificationDuration);
|
||||
const preMinification = Date.now();
|
||||
// Cache both minified and static.
|
||||
const assetCache = new CachingMiddleware();
|
||||
args.app.all(/\/javascripts\/(.*)/, assetCache.handle);
|
||||
|
@ -18,6 +21,10 @@ exports.expressCreateServer = (hookName, args, cb) => {
|
|||
// Setup middleware that will package JavaScript files served by minify for
|
||||
// CommonJS loader on the client-side.
|
||||
// Hostname "invalid.invalid" is a dummy value to allow parsing as a URI.
|
||||
const minificationDuration = Date.now() - preMinification;
|
||||
|
||||
stats.gauge('YajsmlDuration', () => yajsmlDuration);
|
||||
const preYajsml = Date.now();
|
||||
const jsServer = new (Yajsml.Server)({
|
||||
rootPath: 'javascripts/src/',
|
||||
rootURI: 'http://invalid.invalid/static/js/',
|
||||
|
@ -33,6 +40,7 @@ exports.expressCreateServer = (hookName, args, cb) => {
|
|||
jsServer.setAssociator(associator);
|
||||
|
||||
args.app.use(jsServer.handle.bind(jsServer));
|
||||
const yajsmlDuration = Date.now() - preYajsml;
|
||||
|
||||
// serve plugin definitions
|
||||
// not very static, but served here so that client can do
|
||||
|
|
|
@ -93,6 +93,8 @@ exports.start = async () => {
|
|||
|
||||
// start up stats counting system
|
||||
const stats = require('./stats');
|
||||
const startDurations = {};
|
||||
stats.gauge('startDurations', () => startDurations);
|
||||
stats.gauge('memoryUsage', () => process.memoryUsage().rss);
|
||||
stats.gauge('memoryUsageHeap', () => process.memoryUsage().heapUsed);
|
||||
|
||||
|
@ -117,13 +119,26 @@ exports.start = async () => {
|
|||
});
|
||||
}
|
||||
|
||||
const preNpmLoad = Date.now();
|
||||
await util.promisify(npm.load)();
|
||||
startDurations.npmLoad = Date.now() - preNpmLoad;
|
||||
|
||||
const preDbInit = Date.now();
|
||||
await db.init();
|
||||
startDurations.dbInit = Date.now() - preDbInit;
|
||||
|
||||
const prePluginsUpdate = Date.now();
|
||||
await plugins.update();
|
||||
startDurations.loadPlugins = Date.now() - prePluginsUpdate;
|
||||
|
||||
console.info(`Installed plugins: ${plugins.formatPluginsWithVersion()}`);
|
||||
console.debug(`Installed parts:\n${plugins.formatParts()}`);
|
||||
console.debug(`Installed hooks:\n${plugins.formatHooks()}`);
|
||||
|
||||
const preLoadSettings = Date.now();
|
||||
await hooks.aCallAll('loadSettings', {settings});
|
||||
startDurations.loadSettings = Date.now() - preLoadSettings;
|
||||
|
||||
await hooks.aCallAll('createServer');
|
||||
|
||||
console.log('Etherpad is running');
|
||||
|
|
|
@ -38,16 +38,48 @@
|
|||
"z-schema": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"@azure/abort-controller": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.2.tgz",
|
||||
"integrity": "sha512-XUyTo+bcyxHEf+jlN2MXA7YU9nxVehaubngHV1MIZZaqYmZqykkoeAz/JMMEeR7t3TcyDwbFa3Zw8BZywmIx4g==",
|
||||
"requires": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@azure/core-auth": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.1.4.tgz",
|
||||
"integrity": "sha512-+j1embyH1jqf04AIfJPdLafd5SC1y6z1Jz4i+USR1XkTp6KM8P5u4/AjmWMVoEQdM/M29PJcRDZcCEWjK9S1bw==",
|
||||
"requires": {
|
||||
"@azure/abort-controller": "^1.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
|
||||
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@azure/ms-rest-azure-env": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/ms-rest-azure-env/-/ms-rest-azure-env-2.0.0.tgz",
|
||||
"integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw=="
|
||||
},
|
||||
"@azure/ms-rest-js": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.1.0.tgz",
|
||||
"integrity": "sha512-4BXLVImYRt+jcUmEJ5LUWglI8RBNVQndY6IcyvQ4U8O4kIXdmlRz3cJdA/RpXf5rKT38KOoTO2T6Z1f6Z1HDBg==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.2.0.tgz",
|
||||
"integrity": "sha512-lmSqjNuqx/TmwXLpVs1acAExUhHGkHvXIdfyttNc3qlpcn6xoT8JqGFRVwvoh5rZKPfy84aSaXUEPf/gwfRZHg==",
|
||||
"requires": {
|
||||
"@azure/core-auth": "^1.1.4",
|
||||
"@types/node-fetch": "^2.3.7",
|
||||
"@types/tunnel": "0.0.1",
|
||||
"abort-controller": "^3.0.0",
|
||||
|
@ -263,6 +295,11 @@
|
|||
"integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@tediousjs/connection-string": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.3.0.tgz",
|
||||
"integrity": "sha512-d/keJiNKfpHo+GmSB8QcsAwBx8h+V1UbdozA5TD+eSLXprNY53JAYub47J9evsSKWDdNG5uVj0FiMozLKuzowQ=="
|
||||
},
|
||||
"@types/caseless": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||
|
@ -2324,9 +2361,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
|
||||
"integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz",
|
||||
"integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1",
|
||||
|
@ -3397,10 +3434,11 @@
|
|||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"mssql": {
|
||||
"version": "7.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/mssql/-/mssql-7.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-7fOp+QzFf24ir/gGeSvyyGlQKfxZj6tx88vsk4UiQw/t/zpJ9PLjOBOoi6Ff+Tw/CZ1aJTa83MPm+CRYJ/UCQA==",
|
||||
"version": "7.0.0-beta.3",
|
||||
"resolved": "https://registry.npmjs.org/mssql/-/mssql-7.0.0-beta.3.tgz",
|
||||
"integrity": "sha512-Jn/q64Dg2UjbNTqsBwCHFdMjxs4xIVqgWQ1hmDKvBR0T8ebHfPnGTzfNl4oE/VwqP1m0As+v2CMjyqOi9WneuQ==",
|
||||
"requires": {
|
||||
"@tediousjs/connection-string": "^0.3.0",
|
||||
"debug": "^4",
|
||||
"tarn": "^3.0.1",
|
||||
"tedious": "^9.2.3"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
'use strict';
|
||||
/**
|
||||
* API specs
|
||||
*
|
||||
|
@ -11,7 +12,7 @@ const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`)
|
|||
const settings = require(`${__dirname}/../../../../src/node/utils/Settings`);
|
||||
const api = supertest(`http://${settings.ip}:${settings.port}`);
|
||||
|
||||
const validateOpenAPI = require(`${__dirname}/../../../../src/node_modules/openapi-schema-validation`).validate;
|
||||
const validateOpenAPI = require('ep_etherpad-lite/node_modules/openapi-schema-validation').validate;
|
||||
|
||||
const apiKey = common.apiKey;
|
||||
let apiVersion = 1;
|
||||
|
@ -21,6 +22,7 @@ const testPadId = makeid();
|
|||
describe(__filename, function () {
|
||||
describe('API Versioning', function () {
|
||||
it('errors if can not connect', function (done) {
|
||||
this.timeout(150);
|
||||
api
|
||||
.get('/api/')
|
||||
.expect((res) => {
|
||||
|
@ -34,13 +36,15 @@ describe(__filename, function () {
|
|||
|
||||
describe('OpenAPI definition', function () {
|
||||
it('generates valid openapi definition document', function (done) {
|
||||
this.timeout(15000);
|
||||
api
|
||||
.get('/api/openapi.json')
|
||||
.expect((res) => {
|
||||
const {valid, errors} = validateOpenAPI(res.body, 3);
|
||||
if (!valid) {
|
||||
const prettyErrors = JSON.stringify(errors, null, 2);
|
||||
throw new Error(`Document is not valid OpenAPI. ${errors.length} validation errors:\n${prettyErrors}`);
|
||||
throw new Error('Document is not valid OpenAPI. ' +
|
||||
`${errors.length} validation errors:\n${prettyErrors}`);
|
||||
}
|
||||
return;
|
||||
})
|
||||
|
@ -50,6 +54,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('jsonp support', function () {
|
||||
it('supports jsonp calls', function (done) {
|
||||
this.timeout(150);
|
||||
api
|
||||
.get(`${endPoint('createPad')}&jsonp=jsonp_1&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
|
@ -61,9 +66,7 @@ describe(__filename, function () {
|
|||
});
|
||||
});
|
||||
|
||||
var endPoint = function (point) {
|
||||
return `/api/${apiVersion}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
const endPoint = (point) => `/api/${apiVersion}/${point}?apikey=${apiKey}`;
|
||||
|
||||
function makeid() {
|
||||
let text = '';
|
||||
|
|
|
@ -19,6 +19,7 @@ const testPadId = makeid();
|
|||
describe(__filename, function () {
|
||||
describe('Connectivity For Character Encoding', function () {
|
||||
it('can connect', function (done) {
|
||||
this.timeout(250);
|
||||
api.get('/api/')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
|
@ -27,6 +28,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API Versioning', function () {
|
||||
it('finds the version tag', function (done) {
|
||||
this.timeout(150);
|
||||
api.get('/api/')
|
||||
.expect((res) => {
|
||||
apiVersion = res.body.currentVersion;
|
||||
|
@ -39,6 +41,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('Permission', function () {
|
||||
it('errors with invalid APIKey', function (done) {
|
||||
this.timeout(150);
|
||||
// This is broken because Etherpad doesn't handle HTTP codes properly see #2343
|
||||
// If your APIKey is password you deserve to fail all tests anyway
|
||||
const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`;
|
||||
|
@ -49,6 +52,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('createPad', function () {
|
||||
it('creates a new Pad', function (done) {
|
||||
this.timeout(150);
|
||||
api.get(`${endPoint('createPad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to create new Pad');
|
||||
|
@ -60,6 +64,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setHTML', function () {
|
||||
it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function (done) {
|
||||
this.timeout(1000);
|
||||
fs.readFile('../tests/backend/specs/api/emojis.html', 'utf8', (err, html) => {
|
||||
api.post(endPoint('setHTML'))
|
||||
.send({
|
||||
|
@ -77,6 +82,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getHTML', function () {
|
||||
it('get the HTML of Pad with emojis', function (done) {
|
||||
this.timeout(400);
|
||||
api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.html.indexOf('🇼') === -1) {
|
||||
|
@ -95,7 +101,7 @@ describe(__filename, function () {
|
|||
|
||||
*/
|
||||
|
||||
var endPoint = function (point, version) {
|
||||
const endPoint = function (point, version) {
|
||||
version = version || apiVersion;
|
||||
return `/api/${version}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
function m(mod) { return `${__dirname}/../../../../src/${mod}`; }
|
||||
|
||||
const common = require('../../common');
|
||||
|
@ -37,6 +39,7 @@ describe(__filename, function () {
|
|||
*/
|
||||
|
||||
describe('createPad', function () {
|
||||
this.timeout(250);
|
||||
it('creates a new Pad', function (done) {
|
||||
api.get(`${endPoint('createPad')}&padID=${padID}`)
|
||||
.expect((res) => {
|
||||
|
@ -48,10 +51,13 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('createAuthor', function () {
|
||||
this.timeout(100);
|
||||
it('Creates an author with a name set', function (done) {
|
||||
api.get(endPoint('createAuthor'))
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0 || !res.body.data.authorID) throw new Error('Unable to create author');
|
||||
if (res.body.code !== 0 || !res.body.data.authorID) {
|
||||
throw new Error('Unable to create author');
|
||||
}
|
||||
authorID = res.body.data.authorID; // we will be this author for the rest of the tests
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -60,6 +66,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('appendChatMessage', function () {
|
||||
this.timeout(100);
|
||||
it('Adds a chat message to the pad', function (done) {
|
||||
api.get(`${endPoint('appendChatMessage')}&padID=${padID}&text=blalblalbha&authorID=${authorID}&time=${timestamp}`)
|
||||
.expect((res) => {
|
||||
|
@ -72,6 +79,7 @@ describe(__filename, function () {
|
|||
|
||||
|
||||
describe('getChatHead', function () {
|
||||
this.timeout(100);
|
||||
it('Gets the head of chat', function (done) {
|
||||
api.get(`${endPoint('getChatHead')}&padID=${padID}`)
|
||||
.expect((res) => {
|
||||
|
@ -85,10 +93,13 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('getChatHistory', function () {
|
||||
this.timeout(40);
|
||||
it('Gets Chat History of a Pad', function (done) {
|
||||
api.get(`${endPoint('getChatHistory')}&padID=${padID}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.messages.length !== 1) throw new Error('Chat History Length is wrong');
|
||||
if (res.body.data.messages.length !== 1) {
|
||||
throw new Error('Chat History Length is wrong');
|
||||
}
|
||||
if (res.body.code !== 0) throw new Error('Unable to get chat history');
|
||||
})
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -97,7 +108,7 @@ describe(__filename, function () {
|
|||
});
|
||||
});
|
||||
|
||||
var endPoint = function (point) {
|
||||
const endPoint = function (point) {
|
||||
return `/api/${apiVersion}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
|
||||
|
|
|
@ -236,6 +236,7 @@ describe(__filename, function () {
|
|||
});
|
||||
}
|
||||
it('createPad', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('createPad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to create new Pad');
|
||||
|
@ -245,6 +246,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('setHTML', function (done) {
|
||||
this.timeout(150);
|
||||
api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${encodeURIComponent(test.input)}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error(`Error:${testName}`);
|
||||
|
@ -254,6 +256,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('getHTML', function (done) {
|
||||
this.timeout(150);
|
||||
api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
const gotHtml = res.body.data.html;
|
||||
|
@ -277,6 +280,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('getText', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
const gotText = res.body.data.text;
|
||||
|
|
|
@ -26,10 +26,12 @@ const testPadId = makeid();
|
|||
const testPadIdEnc = encodeURIComponent(testPadId);
|
||||
|
||||
describe(__filename, function () {
|
||||
this.timeout(45000);
|
||||
before(async function () { agent = await common.init(); });
|
||||
|
||||
describe('Connectivity', function () {
|
||||
it('can connect', async function () {
|
||||
this.timeout(250);
|
||||
await agent.get('/api/')
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/);
|
||||
|
@ -38,6 +40,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API Versioning', function () {
|
||||
it('finds the version tag', async function () {
|
||||
this.timeout;
|
||||
await agent.get('/api/')
|
||||
.expect(200)
|
||||
.expect((res) => assert(res.body.currentVersion));
|
||||
|
@ -93,6 +96,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('creates a new Pad, imports content to it, checks that content', async function () {
|
||||
this.timeout(500);
|
||||
await agent.get(`${endPoint('createPad')}&padID=${testPadId}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -106,6 +110,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('gets read only pad Id and exports the html and text for this pad', async function () {
|
||||
this.timeout(250);
|
||||
const ro = await agent.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`)
|
||||
.expect(200)
|
||||
.expect((res) => assert.ok(JSON.parse(res.text).data.readOnlyID));
|
||||
|
@ -132,6 +137,7 @@ describe(__filename, function () {
|
|||
// For some reason word import does not work in testing..
|
||||
// TODO: fix support for .doc files..
|
||||
it('Tries to import .doc that uses soffice or abiword', async function () {
|
||||
this.timeout(10000);
|
||||
await agent.post(`/p/${testPadId}/import`)
|
||||
.attach('file', wordDoc, {filename: '/test.doc', contentType: 'application/msword'})
|
||||
.expect(200)
|
||||
|
@ -139,6 +145,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('exports DOC', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.get(`/p/${testPadId}/export/doc`)
|
||||
.buffer(true).parse(superagent.parse['application/octet-stream'])
|
||||
.expect(200)
|
||||
|
@ -146,6 +153,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('Tries to import .docx that uses soffice or abiword', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.post(`/p/${testPadId}/import`)
|
||||
.attach('file', wordXDoc, {
|
||||
filename: '/test.docx',
|
||||
|
@ -157,6 +165,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('exports DOC from imported DOCX', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.get(`/p/${testPadId}/export/doc`)
|
||||
.buffer(true).parse(superagent.parse['application/octet-stream'])
|
||||
.expect(200)
|
||||
|
@ -164,6 +173,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('Tries to import .pdf that uses soffice or abiword', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.post(`/p/${testPadId}/import`)
|
||||
.attach('file', pdfDoc, {filename: '/test.pdf', contentType: 'application/pdf'})
|
||||
.expect(200)
|
||||
|
@ -171,6 +181,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('exports PDF', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.get(`/p/${testPadId}/export/pdf`)
|
||||
.buffer(true).parse(superagent.parse['application/octet-stream'])
|
||||
.expect(200)
|
||||
|
@ -178,6 +189,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('Tries to import .odt that uses soffice or abiword', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.post(`/p/${testPadId}/import`)
|
||||
.attach('file', odtDoc, {filename: '/test.odt', contentType: 'application/odt'})
|
||||
.expect(200)
|
||||
|
@ -185,6 +197,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('exports ODT', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.get(`/p/${testPadId}/export/odt`)
|
||||
.buffer(true).parse(superagent.parse['application/octet-stream'])
|
||||
.expect(200)
|
||||
|
@ -193,6 +206,7 @@ describe(__filename, function () {
|
|||
}); // End of AbiWord/LibreOffice tests.
|
||||
|
||||
it('Tries to import .etherpad', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.post(`/p/${testPadId}/import`)
|
||||
.attach('file', etherpadDoc, {
|
||||
filename: '/test.etherpad',
|
||||
|
@ -203,6 +217,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('exports Etherpad', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.get(`/p/${testPadId}/export/etherpad`)
|
||||
.buffer(true).parse(superagent.parse.text)
|
||||
.expect(200)
|
||||
|
@ -210,6 +225,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('exports HTML for this Etherpad file', async function () {
|
||||
this.timeout(3000);
|
||||
await agent.get(`/p/${testPadId}/export/html`)
|
||||
.expect(200)
|
||||
.expect('content-type', 'text/html; charset=utf-8')
|
||||
|
@ -217,6 +233,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('Tries to import unsupported file type', async function () {
|
||||
this.timeout(3000);
|
||||
settings.allowUnknownFileEnds = false;
|
||||
await agent.post(`/p/${testPadId}/import`)
|
||||
.attach('file', padText, {filename: '/test.xasdasdxx', contentType: 'weirdness/jobby'})
|
||||
|
@ -252,6 +269,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('!authn !exist -> create', async function () {
|
||||
this.timeout(100);
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
.attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'})
|
||||
.expect(200);
|
||||
|
@ -261,6 +279,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('!authn exist -> replace', async function () {
|
||||
this.timeout(100);
|
||||
const pad = await createTestPad('before import');
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
.attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'})
|
||||
|
@ -270,6 +289,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn anonymous !exist -> fail', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
.attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'})
|
||||
|
@ -278,6 +298,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn anonymous exist -> fail', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
const pad = await createTestPad('before import\n');
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
|
@ -287,6 +308,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn user create !exist -> create', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
.auth('user', 'user-password')
|
||||
|
@ -298,6 +320,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn user modify !exist -> fail', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
authorize = () => 'modify';
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
|
@ -308,6 +331,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn user readonly !exist -> fail', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
authorize = () => 'readOnly';
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
|
@ -318,6 +342,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn user create exist -> replace', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
const pad = await createTestPad('before import\n');
|
||||
await agent.post(`/p/${testPadIdEnc}/import`)
|
||||
|
@ -328,6 +353,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn user modify exist -> replace', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
authorize = () => 'modify';
|
||||
const pad = await createTestPad('before import\n');
|
||||
|
@ -339,6 +365,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authn user readonly exist -> fail', async function () {
|
||||
this.timeout(100);
|
||||
const pad = await createTestPad('before import\n');
|
||||
settings.requireAuthentication = true;
|
||||
authorize = () => 'readOnly';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
* Tests for the instance-level APIs
|
||||
*
|
||||
|
@ -14,6 +16,7 @@ const apiVersion = '1.2.14';
|
|||
describe(__filename, function () {
|
||||
describe('Connectivity for instance-level API tests', function () {
|
||||
it('can connect', function (done) {
|
||||
this.timeout(150);
|
||||
api.get('/api/')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
|
@ -22,6 +25,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getStats', function () {
|
||||
it('Gets the stats of a running instance', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(endPoint('getStats'))
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('getStats() failed');
|
||||
|
@ -44,7 +48,7 @@ describe(__filename, function () {
|
|||
});
|
||||
});
|
||||
|
||||
var endPoint = function (point, version) {
|
||||
const endPoint = function (point, version) {
|
||||
version = version || apiVersion;
|
||||
return `/api/${version}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
* ACHTUNG: there is a copied & modified version of this file in
|
||||
* <basedir>/tests/container/specs/api/pad.js
|
||||
|
@ -46,6 +48,7 @@ const expectedSpaceHtml = '<!doctype html><html><body><ul class="bullet"><li>one
|
|||
describe(__filename, function () {
|
||||
describe('Connectivity', function () {
|
||||
it('can connect', function (done) {
|
||||
this.timeout(200);
|
||||
api.get('/api/')
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done);
|
||||
|
@ -54,6 +57,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API Versioning', function () {
|
||||
it('finds the version tag', function (done) {
|
||||
this.timeout(150);
|
||||
api.get('/api/')
|
||||
.expect((res) => {
|
||||
apiVersion = res.body.currentVersion;
|
||||
|
@ -66,6 +70,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('Permission', function () {
|
||||
it('errors with invalid APIKey', function (done) {
|
||||
this.timeout(150);
|
||||
// This is broken because Etherpad doesn't handle HTTP codes properly see #2343
|
||||
// If your APIKey is password you deserve to fail all tests anyway
|
||||
const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`;
|
||||
|
@ -118,6 +123,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('deletePad', function () {
|
||||
it('deletes a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('deletePad')}&padID=${testPadId}`)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200, done); // @TODO: we shouldn't expect 200 here since the pad may not exist
|
||||
|
@ -126,6 +132,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('createPad', function () {
|
||||
it('creates a new Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('createPad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to create new Pad');
|
||||
|
@ -137,6 +144,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getRevisionsCount', function () {
|
||||
it('gets revision count of Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to get Revision Count');
|
||||
|
@ -149,6 +157,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getSavedRevisionsCount', function () {
|
||||
it('gets saved revisions count of Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count');
|
||||
|
@ -161,6 +170,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('listSavedRevisions', function () {
|
||||
it('gets saved revision list of Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List');
|
||||
|
@ -173,6 +183,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getHTML', function () {
|
||||
it('get the HTML of Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.html.length <= 1) throw new Error('Unable to get the HTML');
|
||||
|
@ -184,6 +195,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('listAllPads', function () {
|
||||
it('list all pads', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(endPoint('listAllPads'))
|
||||
.expect((res) => {
|
||||
if (res.body.data.padIDs.includes(testPadId) !== true) {
|
||||
|
@ -197,6 +209,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('deletePad', function () {
|
||||
it('deletes a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('deletePad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Deletion failed');
|
||||
|
@ -208,6 +221,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('listAllPads', function () {
|
||||
it('list all pads', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(endPoint('listAllPads'))
|
||||
.expect((res) => {
|
||||
if (res.body.data.padIDs.includes(testPadId) !== false) {
|
||||
|
@ -221,6 +235,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getHTML', function () {
|
||||
it('get the HTML of a Pad -- Should return a failure', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 1) throw new Error('Pad deletion failed');
|
||||
|
@ -232,6 +247,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('createPad', function () {
|
||||
it('creates a new Pad with text', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('createPad')}&padID=${testPadId}&text=testText`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Creation failed');
|
||||
|
@ -243,6 +259,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it('gets the Pad text and expect it to be testText with \n which is a line break', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.text !== 'testText\n') throw new Error('Pad Creation with text');
|
||||
|
@ -254,6 +271,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setText', function () {
|
||||
it('creates a new Pad with text', function (done) {
|
||||
this.timeout(200);
|
||||
api.post(endPoint('setText'))
|
||||
.send({
|
||||
padID: testPadId,
|
||||
|
@ -269,6 +287,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it('gets the Pad text', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.text !== 'testTextTwo\n') throw new Error('Setting Text');
|
||||
|
@ -280,6 +299,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getRevisionsCount', function () {
|
||||
it('gets Revision Count of a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.revisions !== 1) throw new Error('Unable to get text revision count');
|
||||
|
@ -291,6 +311,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('saveRevision', function () {
|
||||
it('saves Revision', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('saveRevision')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to save Revision');
|
||||
|
@ -302,6 +323,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getSavedRevisionsCount', function () {
|
||||
it('gets saved revisions count of Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count');
|
||||
|
@ -314,6 +336,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('listSavedRevisions', function () {
|
||||
it('gets saved revision list of Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List');
|
||||
|
@ -325,6 +348,7 @@ describe(__filename, function () {
|
|||
});
|
||||
describe('padUsersCount', function () {
|
||||
it('gets User Count of a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('padUsersCount')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.padUsersCount !== 0) throw new Error('Incorrect Pad User count');
|
||||
|
@ -336,6 +360,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getReadOnlyID', function () {
|
||||
it('Gets the Read Only ID of a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (!res.body.data.readOnlyID) throw new Error('No Read Only ID for Pad');
|
||||
|
@ -347,6 +372,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('listAuthorsOfPad', function () {
|
||||
it('Get Authors of the Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('listAuthorsOfPad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.authorIDs.length !== 0) throw new Error('# of Authors of pad is not 0');
|
||||
|
@ -358,6 +384,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getLastEdited', function () {
|
||||
it('Get When Pad was left Edited', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (!res.body.data.lastEdited) {
|
||||
|
@ -373,6 +400,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setText', function () {
|
||||
it('creates a new Pad with text', function (done) {
|
||||
this.timeout(200);
|
||||
api.post(endPoint('setText'))
|
||||
.send({
|
||||
padID: testPadId,
|
||||
|
@ -388,6 +416,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getLastEdited', function () {
|
||||
it('Get When Pad was left Edited', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.lastEdited <= lastEdited) {
|
||||
|
@ -401,6 +430,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('padUsers', function () {
|
||||
it('gets User Count of a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('padUsers')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.padUsers.length !== 0) throw new Error('Incorrect Pad Users');
|
||||
|
@ -412,6 +442,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('deletePad', function () {
|
||||
it('deletes a Pad', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('deletePad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Deletion failed');
|
||||
|
@ -427,6 +458,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('createPad', function () {
|
||||
it('creates a new Pad with text', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('createPad')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Creation failed');
|
||||
|
@ -437,6 +469,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('setText', function () {
|
||||
this.timeout(200);
|
||||
it('Sets text on a pad Id', function (done) {
|
||||
api.post(`${endPoint('setText')}&padID=${testPadId}`)
|
||||
.field({text})
|
||||
|
@ -450,6 +483,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it('Gets text on a pad Id', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Get Text failed');
|
||||
|
@ -462,6 +496,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setText', function () {
|
||||
it('Sets text on a pad Id including an explicit newline', function (done) {
|
||||
this.timeout(200);
|
||||
api.post(`${endPoint('setText')}&padID=${testPadId}`)
|
||||
.field({text: `${text}\n`})
|
||||
.expect((res) => {
|
||||
|
@ -474,6 +509,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it("Gets text on a pad Id and doesn't have an excess newline", function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Get Text failed');
|
||||
|
@ -486,6 +522,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getLastEdited', function () {
|
||||
it('Gets when pad was last edited', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed');
|
||||
|
@ -497,6 +534,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('movePad', function () {
|
||||
it('Move a Pad to a different Pad ID', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('movePad')}&sourceID=${testPadId}&destinationID=${newPadId}&force=true`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Moving Pad Failed');
|
||||
|
@ -508,6 +546,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it('Gets text on a pad Id', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${newPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed');
|
||||
|
@ -519,6 +558,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('movePad', function () {
|
||||
it('Move a Pad to a different Pad ID', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('movePad')}&sourceID=${newPadId}&destinationID=${testPadId}&force=false`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Moving Pad Failed');
|
||||
|
@ -530,6 +570,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it('Gets text on a pad Id', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed');
|
||||
|
@ -541,6 +582,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getLastEdited', function () {
|
||||
it('Gets when pad was last edited', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed');
|
||||
|
@ -552,6 +594,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('appendText', function () {
|
||||
it('Append text to a pad Id', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('appendText', '1.2.13')}&padID=${testPadId}&text=hello`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Append Text failed');
|
||||
|
@ -563,6 +606,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getText', function () {
|
||||
it('Gets text on a pad Id', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getText')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Pad Get Text failed');
|
||||
|
@ -576,6 +620,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setHTML', function () {
|
||||
it('Sets the HTML of a Pad attempting to pass ugly HTML', function (done) {
|
||||
this.timeout(100);
|
||||
const html = '<div><b>Hello HTML</title></head></div>';
|
||||
api.post(endPoint('setHTML'))
|
||||
.send({
|
||||
|
@ -592,6 +637,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setHTML', function () {
|
||||
it('Sets the HTML of a Pad with complex nested lists of different types', function (done) {
|
||||
this.timeout(100);
|
||||
api.post(endPoint('setHTML'))
|
||||
.send({
|
||||
padID: testPadId,
|
||||
|
@ -607,6 +653,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getHTML', function () {
|
||||
it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
const receivedHtml = res.body.data.html.replace('<br></body>', '</body>').toLowerCase();
|
||||
|
@ -630,6 +677,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('setHTML', function () {
|
||||
it('Sets the HTML of a Pad with white space between list items', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${ulSpaceHtml}`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('List HTML cant be imported');
|
||||
|
@ -641,6 +689,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('getHTML', function () {
|
||||
it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) {
|
||||
this.timeout(100);
|
||||
api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
|
||||
.expect((res) => {
|
||||
const receivedHtml = res.body.data.html.replace('<br></body>', '</body>').toLowerCase();
|
||||
|
@ -663,6 +712,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('createPad', function () {
|
||||
it('errors if pad can be created', function (done) {
|
||||
this.timeout(200);
|
||||
const badUrlChars = ['/', '%23', '%3F', '%26'];
|
||||
async.map(
|
||||
badUrlChars,
|
||||
|
@ -680,6 +730,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('copyPad', function () {
|
||||
it('copies the content of a existent pad', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('copyPad')}&sourceID=${testPadId}&destinationID=${copiedPadId}&force=true`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Copy Pad Failed');
|
||||
|
@ -702,6 +753,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('returns a successful response', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed');
|
||||
|
@ -712,6 +764,7 @@ describe(__filename, function () {
|
|||
|
||||
// this test validates if the source pad's text and attributes are kept
|
||||
it('creates a new pad with the same content as the source pad', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`)
|
||||
.expect((res) => {
|
||||
if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed');
|
||||
|
@ -741,6 +794,7 @@ describe(__filename, function () {
|
|||
const padId = makeid();
|
||||
const padWithNonExistentGroup = `notExistentGroup$${padId}`;
|
||||
it('throws an error', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padWithNonExistentGroup}&force=true`)
|
||||
.expect((res) => {
|
||||
// code 1, it means an error has happened
|
||||
|
@ -759,6 +813,7 @@ describe(__filename, function () {
|
|||
|
||||
context('and force is false', function () {
|
||||
it('throws an error', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=false`)
|
||||
.expect((res) => {
|
||||
// code 1, it means an error has happened
|
||||
|
@ -770,6 +825,7 @@ describe(__filename, function () {
|
|||
|
||||
context('and force is true', function () {
|
||||
it('returns a successful response', function (done) {
|
||||
this.timeout(200);
|
||||
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=true`)
|
||||
.expect((res) => {
|
||||
// code 1, it means an error has happened
|
||||
|
@ -787,7 +843,7 @@ describe(__filename, function () {
|
|||
|
||||
*/
|
||||
|
||||
var createNewPadWithHtml = function (padId, html, cb) {
|
||||
const createNewPadWithHtml = function (padId, html, cb) {
|
||||
api.get(`${endPoint('createPad')}&padID=${padId}`)
|
||||
.end(() => {
|
||||
api.post(endPoint('setHTML'))
|
||||
|
@ -799,7 +855,7 @@ var createNewPadWithHtml = function (padId, html, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
var endPoint = function (point, version) {
|
||||
const endPoint = function (point, version) {
|
||||
version = version || apiVersion;
|
||||
return `/api/${version}/${point}?apikey=${apiKey}`;
|
||||
};
|
||||
|
@ -829,13 +885,13 @@ Array.prototype.equals = function (array) {
|
|||
// if the other array is a falsy value, return
|
||||
if (!array) return false;
|
||||
// compare lengths - can save a lot of time
|
||||
if (this.length != array.length) return false;
|
||||
if (this.length !== array.length) return false;
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
// Check if we have nested arrays
|
||||
if (this[i] instanceof Array && array[i] instanceof Array) {
|
||||
// recurse into the nested arrays
|
||||
if (!this[i].equals(array[i])) return false;
|
||||
} else if (this[i] != array[i]) {
|
||||
} else if (this[i] !== array[i]) {
|
||||
// Warning - two different object instances will never be equal: {x:20} != {x:20}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('assert').strict;
|
||||
const common = require('../../common');
|
||||
const supertest = require(`${__dirname}/../../../../src/node_modules/supertest`);
|
||||
|
@ -14,6 +16,7 @@ let padID = makeid();
|
|||
describe(__filename, function () {
|
||||
describe('API Versioning', function () {
|
||||
it('errors if can not connect', async function () {
|
||||
this.timeout(200);
|
||||
await api.get('/api/')
|
||||
.expect(200)
|
||||
.expect((res) => {
|
||||
|
@ -55,6 +58,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API: Group creation and deletion', function () {
|
||||
it('createGroup', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(endPoint('createGroup'))
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -66,6 +70,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('listSessionsOfGroup for empty group', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -76,6 +81,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('deleteGroup', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('deleteGroup')}&groupID=${groupID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -85,6 +91,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('createGroupIfNotExistsFor', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('createGroupIfNotExistsFor')}&groupMapper=management`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -174,6 +181,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API: Author creation', function () {
|
||||
it('createGroup', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(endPoint('createGroup'))
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -185,6 +193,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('createAuthor', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(endPoint('createAuthor'))
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -195,6 +204,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('createAuthor with name', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('createAuthor')}&name=john`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -206,6 +216,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('createAuthorIfNotExistsFor', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('createAuthorIfNotExistsFor')}&authorMapper=chris`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -216,6 +227,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('getAuthorName', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('getAuthorName')}&authorID=${authorID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -228,6 +240,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API: Sessions', function () {
|
||||
it('createSession', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('createSession')
|
||||
}&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`)
|
||||
.expect(200)
|
||||
|
@ -240,6 +253,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('getSessionInfo', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -252,6 +266,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('listSessionsOfGroup', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -262,6 +277,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('deleteSession', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('deleteSession')}&sessionID=${sessionID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -271,6 +287,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('getSessionInfo of deleted session', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -282,6 +299,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API: Group pad management', function () {
|
||||
it('listPads', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('listPads')}&groupID=${groupID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -292,6 +310,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('createGroupPad', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=${padID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -302,6 +321,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('listPads after creating a group pad', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('listPads')}&groupID=${groupID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -314,6 +334,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API: Pad security', function () {
|
||||
it('getPublicStatus', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -324,6 +345,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('setPublicStatus', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('setPublicStatus')}&padID=${padID}&publicStatus=true`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -333,6 +355,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('getPublicStatus after changing public status', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
@ -349,6 +372,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('API: Misc', function () {
|
||||
it('listPadsOfAuthor', async function () {
|
||||
this.timeout(100);
|
||||
await api.get(`${endPoint('listPadsOfAuthor')}&authorID=${authorID}`)
|
||||
.expect(200)
|
||||
.expect('Content-Type', /json/)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* caching_middleware is responsible for serving everything under path `/javascripts/`
|
||||
* That includes packages as defined in `src/node/utils/tar.json` and probably also plugin code
|
||||
|
@ -43,6 +45,7 @@ function disableAutoDeflate(request) {
|
|||
}
|
||||
|
||||
describe(__filename, function () {
|
||||
this.timeout(40000);
|
||||
const backups = {};
|
||||
const fantasyEncoding = 'brainwaves'; // non-working encoding until https://github.com/visionmedia/superagent/pull/1560 is resolved
|
||||
const packages = [
|
||||
|
@ -68,6 +71,7 @@ describe(__filename, function () {
|
|||
settings.minify = false;
|
||||
});
|
||||
it('gets packages uncompressed without Accept-Encoding gzip', async function () {
|
||||
this.timeout(2500);
|
||||
await Promise.all(packages.map(async (resource) => agent.get(resource)
|
||||
.set('Accept-Encoding', fantasyEncoding)
|
||||
.use(disableAutoDeflate)
|
||||
|
@ -80,6 +84,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('gets packages compressed with Accept-Encoding gzip', async function () {
|
||||
this.timeout(1500);
|
||||
await Promise.all(packages.map(async (resource) => agent.get(resource)
|
||||
.set('Accept-Encoding', 'gzip')
|
||||
.use(disableAutoDeflate)
|
||||
|
@ -92,6 +97,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('does not cache content-encoding headers', async function () {
|
||||
this.timeout(1500);
|
||||
await agent.get(packages[0])
|
||||
.set('Accept-Encoding', fantasyEncoding)
|
||||
.then((res) => assert.equal(res.header['content-encoding'], undefined));
|
||||
|
@ -109,6 +115,7 @@ describe(__filename, function () {
|
|||
settings.minify = true;
|
||||
});
|
||||
it('gets packages uncompressed without Accept-Encoding gzip', async function () {
|
||||
this.timeout(1500);
|
||||
await Promise.all(packages.map(async (resource) => agent.get(resource)
|
||||
.set('Accept-Encoding', fantasyEncoding)
|
||||
.use(disableAutoDeflate)
|
||||
|
@ -121,6 +128,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('gets packages compressed with Accept-Encoding gzip', async function () {
|
||||
this.timeout(1500);
|
||||
await Promise.all(packages.map(async (resource) => agent.get(resource)
|
||||
.set('Accept-Encoding', 'gzip')
|
||||
.use(disableAutoDeflate)
|
||||
|
@ -133,6 +141,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('does not cache content-encoding headers', async function () {
|
||||
this.timeout(1500);
|
||||
await agent.get(packages[0])
|
||||
.set('Accept-Encoding', fantasyEncoding)
|
||||
.then((res) => assert.equal(res.header['content-encoding'], undefined));
|
||||
|
|
|
@ -285,6 +285,7 @@ describe(__filename, function () {
|
|||
}
|
||||
|
||||
it(testObj.description, async function () {
|
||||
this.timeout(250);
|
||||
const $ = cheerio.load(testObj.html); // Load HTML into Cheerio
|
||||
const doc = $('body')[0]; // Creates a dom-like representation of HTML
|
||||
// Create an empty attribute pool
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('assert').strict;
|
||||
const hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
const plugins = require('ep_etherpad-lite/static/js/pluginfw/plugin_defs');
|
||||
|
@ -93,11 +92,13 @@ describe(__filename, function () {
|
|||
|
||||
describe('basic behavior', function () {
|
||||
it('passes hook name', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
|
||||
callHookFnSync(hook);
|
||||
});
|
||||
|
||||
it('passes context', async function () {
|
||||
this.timeout(30);
|
||||
for (const val of ['value', null, undefined]) {
|
||||
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); };
|
||||
callHookFnSync(hook, val);
|
||||
|
@ -105,6 +106,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('returns the value provided to the callback', async function () {
|
||||
this.timeout(30);
|
||||
for (const val of ['value', null, undefined]) {
|
||||
hook.hook_fn = (hn, ctx, cb) => { cb(ctx); };
|
||||
assert.equal(callHookFnSync(hook, val), val);
|
||||
|
@ -112,6 +114,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('returns the value returned by the hook function', async function () {
|
||||
this.timeout(30);
|
||||
for (const val of ['value', null, undefined]) {
|
||||
// Must not have the cb parameter otherwise returning undefined will error.
|
||||
hook.hook_fn = (hn, ctx) => ctx;
|
||||
|
@ -120,16 +123,19 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('does not catch exceptions', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = () => { throw new Error('test exception'); };
|
||||
assert.throws(() => callHookFnSync(hook), {message: 'test exception'});
|
||||
});
|
||||
|
||||
it('callback returns undefined', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); };
|
||||
callHookFnSync(hook);
|
||||
});
|
||||
|
||||
it('checks for deprecation', async function () {
|
||||
this.timeout(30);
|
||||
sinon.stub(console, 'warn');
|
||||
hooks.deprecationNotices[hookName] = 'test deprecation';
|
||||
callHookFnSync(hook);
|
||||
|
@ -140,6 +146,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('supported hook function styles', function () {
|
||||
this.timeout(30);
|
||||
for (const tc of supportedSyncHookFunctions) {
|
||||
it(tc.name, async function () {
|
||||
sinon.stub(console, 'warn');
|
||||
|
@ -158,6 +165,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('bad hook function behavior (other than double settle)', function () {
|
||||
this.timeout(30);
|
||||
const promise1 = Promise.resolve('val1');
|
||||
const promise2 = Promise.resolve('val2');
|
||||
|
||||
|
@ -237,6 +245,7 @@ describe(__filename, function () {
|
|||
if (step1.async && step2.async) continue;
|
||||
|
||||
it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx, cb) => {
|
||||
step1.fn(cb, new Error(ctx.ret1), ctx.ret1);
|
||||
return step2.fn(cb, new Error(ctx.ret2), ctx.ret2);
|
||||
|
@ -300,6 +309,7 @@ describe(__filename, function () {
|
|||
if (step1.rejects !== step2.rejects) continue;
|
||||
|
||||
it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () {
|
||||
this.timeout(30);
|
||||
const err = new Error('val');
|
||||
hook.hook_fn = (hn, ctx, cb) => {
|
||||
step1.fn(cb, err, 'val');
|
||||
|
@ -325,27 +335,32 @@ describe(__filename, function () {
|
|||
describe('hooks.callAll', function () {
|
||||
describe('basic behavior', function () {
|
||||
it('calls all in order', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(1), makeHook(2), makeHook(3));
|
||||
assert.deepEqual(hooks.callAll(hookName), [1, 2, 3]);
|
||||
});
|
||||
|
||||
it('passes hook name', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
|
||||
hooks.callAll(hookName);
|
||||
});
|
||||
|
||||
it('undefined context -> {}', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
|
||||
hooks.callAll(hookName);
|
||||
});
|
||||
|
||||
it('null context -> {}', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
|
||||
hooks.callAll(hookName, null);
|
||||
});
|
||||
|
||||
it('context unmodified', async function () {
|
||||
this.timeout(30);
|
||||
const wantContext = {};
|
||||
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); };
|
||||
hooks.callAll(hookName, wantContext);
|
||||
|
@ -354,34 +369,40 @@ describe(__filename, function () {
|
|||
|
||||
describe('result processing', function () {
|
||||
it('no registered hooks (undefined) -> []', async function () {
|
||||
this.timeout(30);
|
||||
delete plugins.hooks.testHook;
|
||||
assert.deepEqual(hooks.callAll(hookName), []);
|
||||
});
|
||||
|
||||
it('no registered hooks (empty list) -> []', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
assert.deepEqual(hooks.callAll(hookName), []);
|
||||
});
|
||||
|
||||
it('flattens one level', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]]));
|
||||
assert.deepEqual(hooks.callAll(hookName), [1, 2, [3]]);
|
||||
});
|
||||
|
||||
it('filters out undefined', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]));
|
||||
assert.deepEqual(hooks.callAll(hookName), [2, [3]]);
|
||||
});
|
||||
|
||||
it('preserves null', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(null), makeHook([2]), makeHook([[3]]));
|
||||
assert.deepEqual(hooks.callAll(hookName), [null, 2, [3]]);
|
||||
});
|
||||
|
||||
it('all undefined -> []', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(), makeHook());
|
||||
assert.deepEqual(hooks.callAll(hookName), []);
|
||||
|
@ -478,11 +499,13 @@ describe(__filename, function () {
|
|||
|
||||
describe('basic behavior', function () {
|
||||
it('passes hook name', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
|
||||
await callHookFnAsync(hook);
|
||||
});
|
||||
|
||||
it('passes context', async function () {
|
||||
this.timeout(30);
|
||||
for (const val of ['value', null, undefined]) {
|
||||
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); };
|
||||
await callHookFnAsync(hook, val);
|
||||
|
@ -490,6 +513,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('returns the value provided to the callback', async function () {
|
||||
this.timeout(30);
|
||||
for (const val of ['value', null, undefined]) {
|
||||
hook.hook_fn = (hn, ctx, cb) => { cb(ctx); };
|
||||
assert.equal(await callHookFnAsync(hook, val), val);
|
||||
|
@ -498,6 +522,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('returns the value returned by the hook function', async function () {
|
||||
this.timeout(30);
|
||||
for (const val of ['value', null, undefined]) {
|
||||
// Must not have the cb parameter otherwise returning undefined will never resolve.
|
||||
hook.hook_fn = (hn, ctx) => ctx;
|
||||
|
@ -507,26 +532,31 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('rejects if it throws an exception', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = () => { throw new Error('test exception'); };
|
||||
await assert.rejects(callHookFnAsync(hook), {message: 'test exception'});
|
||||
});
|
||||
|
||||
it('rejects if rejected Promise passed to callback', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx, cb) => cb(Promise.reject(new Error('test exception')));
|
||||
await assert.rejects(callHookFnAsync(hook), {message: 'test exception'});
|
||||
});
|
||||
|
||||
it('rejects if rejected Promise returned', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx, cb) => Promise.reject(new Error('test exception'));
|
||||
await assert.rejects(callHookFnAsync(hook), {message: 'test exception'});
|
||||
});
|
||||
|
||||
it('callback returns undefined', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); };
|
||||
await callHookFnAsync(hook);
|
||||
});
|
||||
|
||||
it('checks for deprecation', async function () {
|
||||
this.timeout(30);
|
||||
sinon.stub(console, 'warn');
|
||||
hooks.deprecationNotices[hookName] = 'test deprecation';
|
||||
await callHookFnAsync(hook);
|
||||
|
@ -619,6 +649,7 @@ describe(__filename, function () {
|
|||
|
||||
for (const tc of supportedSyncHookFunctions.concat(supportedHookFunctions)) {
|
||||
it(tc.name, async function () {
|
||||
this.timeout(30);
|
||||
sinon.stub(console, 'warn');
|
||||
sinon.stub(console, 'error');
|
||||
hook.hook_fn = tc.fn;
|
||||
|
@ -766,6 +797,7 @@ describe(__filename, function () {
|
|||
if (step1.name.startsWith('return ') || step1.name === 'throw') continue;
|
||||
for (const step2 of behaviors) {
|
||||
it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = (hn, ctx, cb) => {
|
||||
step1.fn(cb, new Error(ctx.ret1), ctx.ret1);
|
||||
return step2.fn(cb, new Error(ctx.ret2), ctx.ret2);
|
||||
|
@ -819,6 +851,7 @@ describe(__filename, function () {
|
|||
if (step1.rejects !== step2.rejects) continue;
|
||||
|
||||
it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () {
|
||||
this.timeout(30);
|
||||
const err = new Error('val');
|
||||
hook.hook_fn = (hn, ctx, cb) => {
|
||||
step1.fn(cb, err, 'val');
|
||||
|
@ -844,6 +877,7 @@ describe(__filename, function () {
|
|||
describe('hooks.aCallAll', function () {
|
||||
describe('basic behavior', function () {
|
||||
it('calls all asynchronously, returns values in order', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0; // Delete the boilerplate hook -- this test doesn't use it.
|
||||
let nextIndex = 0;
|
||||
const hookPromises = [];
|
||||
|
@ -878,21 +912,25 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('passes hook name', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = async (hn) => { assert.equal(hn, hookName); };
|
||||
await hooks.aCallAll(hookName);
|
||||
});
|
||||
|
||||
it('undefined context -> {}', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); };
|
||||
await hooks.aCallAll(hookName);
|
||||
});
|
||||
|
||||
it('null context -> {}', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); };
|
||||
await hooks.aCallAll(hookName, null);
|
||||
});
|
||||
|
||||
it('context unmodified', async function () {
|
||||
this.timeout(30);
|
||||
const wantContext = {};
|
||||
hook.hook_fn = async (hn, ctx) => { assert.equal(ctx, wantContext); };
|
||||
await hooks.aCallAll(hookName, wantContext);
|
||||
|
@ -901,11 +939,13 @@ describe(__filename, function () {
|
|||
|
||||
describe('aCallAll callback', function () {
|
||||
it('exception in callback rejects', async function () {
|
||||
this.timeout(30);
|
||||
const p = hooks.aCallAll(hookName, {}, () => { throw new Error('test exception'); });
|
||||
await assert.rejects(p, {message: 'test exception'});
|
||||
});
|
||||
|
||||
it('propagates error on exception', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = () => { throw new Error('test exception'); };
|
||||
await hooks.aCallAll(hookName, {}, (err) => {
|
||||
assert(err instanceof Error);
|
||||
|
@ -914,12 +954,14 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('propagages null error on success', async function () {
|
||||
this.timeout(30);
|
||||
await hooks.aCallAll(hookName, {}, (err) => {
|
||||
assert(err == null, `got non-null error: ${err}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('propagages results on success', async function () {
|
||||
this.timeout(30);
|
||||
hook.hook_fn = () => 'val';
|
||||
await hooks.aCallAll(hookName, {}, (err, results) => {
|
||||
assert.deepEqual(results, ['val']);
|
||||
|
@ -927,40 +969,47 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('returns callback return value', async function () {
|
||||
this.timeout(30);
|
||||
assert.equal(await hooks.aCallAll(hookName, {}, () => 'val'), 'val');
|
||||
});
|
||||
});
|
||||
|
||||
describe('result processing', function () {
|
||||
it('no registered hooks (undefined) -> []', async function () {
|
||||
this.timeout(30);
|
||||
delete plugins.hooks[hookName];
|
||||
assert.deepEqual(await hooks.aCallAll(hookName), []);
|
||||
});
|
||||
|
||||
it('no registered hooks (empty list) -> []', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
assert.deepEqual(await hooks.aCallAll(hookName), []);
|
||||
});
|
||||
|
||||
it('flattens one level', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]]));
|
||||
assert.deepEqual(await hooks.aCallAll(hookName), [1, 2, [3]]);
|
||||
});
|
||||
|
||||
it('filters out undefined', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]), makeHook(Promise.resolve()));
|
||||
assert.deepEqual(await hooks.aCallAll(hookName), [2, [3]]);
|
||||
});
|
||||
|
||||
it('preserves null', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(null), makeHook([2]), makeHook(Promise.resolve(null)));
|
||||
assert.deepEqual(await hooks.aCallAll(hookName), [null, 2, null]);
|
||||
});
|
||||
|
||||
it('all undefined -> []', async function () {
|
||||
this.timeout(30);
|
||||
testHooks.length = 0;
|
||||
testHooks.push(makeHook(), makeHook(Promise.resolve()));
|
||||
assert.deepEqual(await hooks.aCallAll(hookName), []);
|
||||
|
|
|
@ -26,10 +26,12 @@ describe(__filename, function () {
|
|||
const timesLimitPromise = promises.timesLimit(total, concurrency, makePromise);
|
||||
|
||||
it('honors concurrency', async function () {
|
||||
this.timeout(50);
|
||||
assert.equal(wantIndex, concurrency);
|
||||
});
|
||||
|
||||
it('creates another when one completes', async function () {
|
||||
this.timeout(50);
|
||||
const {promise, resolve} = testPromises.shift();
|
||||
resolve();
|
||||
await promise;
|
||||
|
@ -37,6 +39,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('creates the expected total number of promises', async function () {
|
||||
this.timeout(50);
|
||||
while (testPromises.length > 0) {
|
||||
// Resolve them in random order to ensure that the resolution order doesn't matter.
|
||||
const i = Math.floor(Math.random() * Math.floor(testPromises.length));
|
||||
|
@ -48,10 +51,12 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('resolves', async function () {
|
||||
this.timeout(50);
|
||||
await timesLimitPromise;
|
||||
});
|
||||
|
||||
it('does not create too many promises if total < concurrency', async function () {
|
||||
this.timeout(50);
|
||||
wantIndex = 0;
|
||||
assert.equal(testPromises.length, 0);
|
||||
const total = 7;
|
||||
|
@ -67,6 +72,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('accepts total === 0, concurrency > 0', async function () {
|
||||
this.timeout(50);
|
||||
wantIndex = 0;
|
||||
assert.equal(testPromises.length, 0);
|
||||
await promises.timesLimit(0, concurrency, makePromise);
|
||||
|
@ -74,6 +80,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('accepts total === 0, concurrency === 0', async function () {
|
||||
this.timeout(50);
|
||||
wantIndex = 0;
|
||||
assert.equal(testPromises.length, 0);
|
||||
await promises.timesLimit(0, 0, makePromise);
|
||||
|
@ -81,6 +88,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('rejects total > 0, concurrency === 0', async function () {
|
||||
this.timeout(50);
|
||||
await assert.rejects(promises.timesLimit(total, 0, makePromise), RangeError);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -89,6 +89,7 @@ const handshake = async (socket, padID) => {
|
|||
};
|
||||
|
||||
describe(__filename, function () {
|
||||
this.timeout(30000);
|
||||
let agent;
|
||||
let authorize;
|
||||
const backups = {};
|
||||
|
@ -136,23 +137,27 @@ describe(__filename, function () {
|
|||
|
||||
describe('Normal accesses', function () {
|
||||
it('!authn anonymous cookie /p/pad -> 200, ok', async function () {
|
||||
this.timeout(600);
|
||||
const res = await agent.get('/p/pad').expect(200);
|
||||
socket = await connect(res);
|
||||
const clientVars = await handshake(socket, 'pad');
|
||||
assert.equal(clientVars.type, 'CLIENT_VARS');
|
||||
});
|
||||
it('!authn !cookie -> ok', async function () {
|
||||
this.timeout(400);
|
||||
socket = await connect(null);
|
||||
const clientVars = await handshake(socket, 'pad');
|
||||
assert.equal(clientVars.type, 'CLIENT_VARS');
|
||||
});
|
||||
it('!authn user /p/pad -> 200, ok', async function () {
|
||||
this.timeout(400);
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
const clientVars = await handshake(socket, 'pad');
|
||||
assert.equal(clientVars.type, 'CLIENT_VARS');
|
||||
});
|
||||
it('authn user /p/pad -> 200, ok', async function () {
|
||||
this.timeout(400);
|
||||
settings.requireAuthentication = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -160,6 +165,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.type, 'CLIENT_VARS');
|
||||
});
|
||||
it('authz user /p/pad -> 200, ok', async function () {
|
||||
this.timeout(400);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -168,6 +174,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.type, 'CLIENT_VARS');
|
||||
});
|
||||
it('supports pad names with characters that must be percent-encoded', async function () {
|
||||
this.timeout(400);
|
||||
settings.requireAuthentication = true;
|
||||
// requireAuthorization is set to true here to guarantee that the user's padAuthorizations
|
||||
// object is populated. Technically this isn't necessary because the user's padAuthorizations
|
||||
|
@ -184,6 +191,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('Abnormal access attempts', function () {
|
||||
it('authn anonymous /p/pad -> 401, error', async function () {
|
||||
this.timeout(400);
|
||||
settings.requireAuthentication = true;
|
||||
const res = await agent.get('/p/pad').expect(401);
|
||||
// Despite the 401, try to create the pad via a socket.io connection anyway.
|
||||
|
@ -192,12 +200,14 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it('authn !cookie -> error', async function () {
|
||||
this.timeout(400);
|
||||
settings.requireAuthentication = true;
|
||||
socket = await connect(null);
|
||||
const message = await handshake(socket, 'pad');
|
||||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it('authorization bypass attempt -> error', async function () {
|
||||
this.timeout(400);
|
||||
// Only allowed to access /p/pad.
|
||||
authorize = (req) => req.path === '/p/pad';
|
||||
settings.requireAuthentication = true;
|
||||
|
@ -218,6 +228,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it("level='create' -> can create", async function () {
|
||||
this.timeout(400);
|
||||
authorize = () => 'create';
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -226,6 +237,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.data.readonly, false);
|
||||
});
|
||||
it('level=true -> can create', async function () {
|
||||
this.timeout(400);
|
||||
authorize = () => true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -234,6 +246,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.data.readonly, false);
|
||||
});
|
||||
it("level='modify' -> can modify", async function () {
|
||||
this.timeout(400);
|
||||
await padManager.getPad('pad'); // Create the pad.
|
||||
authorize = () => 'modify';
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -243,6 +256,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.data.readonly, false);
|
||||
});
|
||||
it("level='create' settings.editOnly=true -> unable to create", async function () {
|
||||
this.timeout(400);
|
||||
authorize = () => 'create';
|
||||
settings.editOnly = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -251,6 +265,7 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it("level='modify' settings.editOnly=false -> unable to create", async function () {
|
||||
this.timeout(400);
|
||||
authorize = () => 'modify';
|
||||
settings.editOnly = false;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -259,6 +274,7 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it("level='readOnly' -> unable to create", async function () {
|
||||
this.timeout(400);
|
||||
authorize = () => 'readOnly';
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -266,6 +282,7 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it("level='readOnly' -> unable to modify", async function () {
|
||||
this.timeout(400);
|
||||
await padManager.getPad('pad'); // Create the pad.
|
||||
authorize = () => 'readOnly';
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -282,6 +299,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('user.canCreate = true -> can create and modify', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.canCreate = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -290,6 +308,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.data.readonly, false);
|
||||
});
|
||||
it('user.canCreate = false -> unable to create', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.canCreate = false;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -297,6 +316,7 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it('user.readOnly = true -> unable to create', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.readOnly = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -304,6 +324,7 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it('user.readOnly = true -> unable to modify', async function () {
|
||||
this.timeout(400);
|
||||
await padManager.getPad('pad'); // Create the pad.
|
||||
settings.users.user.readOnly = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -313,6 +334,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.data.readonly, true);
|
||||
});
|
||||
it('user.readOnly = false -> can create and modify', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.readOnly = false;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
socket = await connect(res);
|
||||
|
@ -321,6 +343,7 @@ describe(__filename, function () {
|
|||
assert.equal(clientVars.data.readonly, false);
|
||||
});
|
||||
it('user.readOnly = true, user.canCreate = true -> unable to create', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.canCreate = true;
|
||||
settings.users.user.readOnly = true;
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -337,6 +360,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('authorize hook does not elevate level from user settings', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.readOnly = true;
|
||||
authorize = () => 'create';
|
||||
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
|
||||
|
@ -345,6 +369,7 @@ describe(__filename, function () {
|
|||
assert.equal(message.accessStatus, 'deny');
|
||||
});
|
||||
it('user settings does not elevate level from authorize hook', async function () {
|
||||
this.timeout(400);
|
||||
settings.users.user.readOnly = false;
|
||||
settings.users.user.canCreate = true;
|
||||
authorize = () => 'readOnly';
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const settings = require('ep_etherpad-lite/node/utils/Settings');
|
||||
|
||||
describe(__filename, function () {
|
||||
this.timeout(30000);
|
||||
let agent;
|
||||
const backups = {};
|
||||
before(async function () { agent = await common.init(); });
|
||||
|
@ -19,6 +22,7 @@ describe(__filename, function () {
|
|||
|
||||
describe('/javascript', function () {
|
||||
it('/javascript -> 200', async function () {
|
||||
this.timeout(200);
|
||||
await agent.get('/javascript').expect(200);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@ const plugins = require('ep_etherpad-lite/static/js/pluginfw/plugin_defs');
|
|||
const settings = require('ep_etherpad-lite/node/utils/Settings');
|
||||
|
||||
describe(__filename, function () {
|
||||
this.timeout(30000);
|
||||
let agent;
|
||||
const backups = {};
|
||||
const authHookNames = ['preAuthorize', 'authenticate', 'authorize'];
|
||||
|
@ -42,56 +43,67 @@ describe(__filename, function () {
|
|||
|
||||
describe('webaccess: without plugins', function () {
|
||||
it('!authn !authz anonymous / -> 200', async function () {
|
||||
this.timeout(150);
|
||||
settings.requireAuthentication = false;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/').expect(200);
|
||||
});
|
||||
it('!authn !authz anonymous /admin/ -> 401', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = false;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').expect(401);
|
||||
});
|
||||
it('authn !authz anonymous / -> 401', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/').expect(401);
|
||||
});
|
||||
it('authn !authz user / -> 200', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/').auth('user', 'user-password').expect(200);
|
||||
});
|
||||
it('authn !authz user /admin/ -> 403', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').auth('user', 'user-password').expect(403);
|
||||
});
|
||||
it('authn !authz admin / -> 200', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
it('authn !authz admin /admin/ -> 200', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
it('authn authz user / -> 403', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/').auth('user', 'user-password').expect(403);
|
||||
});
|
||||
it('authn authz user /admin/ -> 403', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/admin/').auth('user', 'user-password').expect(403);
|
||||
});
|
||||
it('authn authz admin / -> 200', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
it('authn authz admin /admin/ -> 200', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
|
||||
|
@ -105,6 +117,7 @@ describe(__filename, function () {
|
|||
// parsing, resulting in successful comparisons against a null or undefined password.
|
||||
for (const creds of ['admin', 'admin:']) {
|
||||
it(`admin password: ${adminPassword} credentials: ${creds}`, async function () {
|
||||
this.timeout(100);
|
||||
settings.users.admin.password = adminPassword;
|
||||
const encCreds = Buffer.from(creds).toString('base64');
|
||||
await agent.get('/admin/').set('Authorization', `Basic ${encCreds}`).expect(401);
|
||||
|
@ -160,11 +173,13 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('defers if it returns []', async function () {
|
||||
this.timeout(100);
|
||||
await agent.get('/').expect(200);
|
||||
// Note: The preAuthorize hook always runs even if requireAuthorization is false.
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
|
||||
});
|
||||
it('bypasses authenticate and authorize hooks when true is returned', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
handlers.preAuthorize[0].innerHandle = () => [true];
|
||||
|
@ -172,6 +187,7 @@ describe(__filename, function () {
|
|||
assert.deepEqual(callOrder, ['preAuthorize_0']);
|
||||
});
|
||||
it('bypasses authenticate and authorize hooks when false is returned', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
handlers.preAuthorize[0].innerHandle = () => [false];
|
||||
|
@ -179,12 +195,14 @@ describe(__filename, function () {
|
|||
assert.deepEqual(callOrder, ['preAuthorize_0']);
|
||||
});
|
||||
it('bypasses authenticate and authorize hooks for static content, defers', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/static/robots.txt').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
|
||||
});
|
||||
it('cannot grant access to /admin', async function () {
|
||||
this.timeout(100);
|
||||
handlers.preAuthorize[0].innerHandle = () => [true];
|
||||
await agent.get('/admin/').expect(401);
|
||||
// Notes:
|
||||
|
@ -198,11 +216,13 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('can deny access to /admin', async function () {
|
||||
this.timeout(100);
|
||||
handlers.preAuthorize[0].innerHandle = () => [false];
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(403);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0']);
|
||||
});
|
||||
it('runs preAuthzFailure hook when access is denied', async function () {
|
||||
this.timeout(100);
|
||||
handlers.preAuthorize[0].innerHandle = () => [false];
|
||||
let called = false;
|
||||
plugins.hooks.preAuthzFailure = [makeHook('preAuthzFailure', (hookName, {req, res}, cb) => {
|
||||
|
@ -218,6 +238,7 @@ describe(__filename, function () {
|
|||
assert(called);
|
||||
});
|
||||
it('returns 500 if an exception is thrown', async function () {
|
||||
this.timeout(100);
|
||||
handlers.preAuthorize[0].innerHandle = () => { throw new Error('exception test'); };
|
||||
await agent.get('/').expect(500);
|
||||
});
|
||||
|
@ -230,11 +251,13 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('is not called if !requireAuthentication and not /admin/*', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = false;
|
||||
await agent.get('/').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
|
||||
});
|
||||
it('is called if !requireAuthentication and /admin/*', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthentication = false;
|
||||
await agent.get('/admin/').expect(401);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
|
@ -243,6 +266,7 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('defers if empty list returned', async function () {
|
||||
this.timeout(100);
|
||||
await agent.get('/').expect(401);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
'preAuthorize_1',
|
||||
|
@ -250,18 +274,21 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('does not defer if return [true], 200', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].innerHandle = (req) => { req.session.user = {}; return [true]; };
|
||||
await agent.get('/').expect(200);
|
||||
// Note: authenticate_1 was not called because authenticate_0 handled it.
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
|
||||
});
|
||||
it('does not defer if return [false], 401', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].innerHandle = (req) => [false];
|
||||
await agent.get('/').expect(401);
|
||||
// Note: authenticate_1 was not called because authenticate_0 handled it.
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
|
||||
});
|
||||
it('falls back to HTTP basic auth', async function () {
|
||||
this.timeout(100);
|
||||
await agent.get('/').auth('user', 'user-password').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
'preAuthorize_1',
|
||||
|
@ -269,6 +296,7 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('passes settings.users in context', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].checkContext = ({users}) => {
|
||||
assert.equal(users, settings.users);
|
||||
};
|
||||
|
@ -279,6 +307,7 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('passes user, password in context if provided', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].checkContext = ({username, password}) => {
|
||||
assert.equal(username, 'user');
|
||||
assert.equal(password, 'user-password');
|
||||
|
@ -290,6 +319,7 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('does not pass user, password in context if not provided', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].checkContext = ({username, password}) => {
|
||||
assert(username == null);
|
||||
assert(password == null);
|
||||
|
@ -301,11 +331,13 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('errors if req.session.user is not created', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].innerHandle = () => [true];
|
||||
await agent.get('/').expect(500);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
|
||||
});
|
||||
it('returns 500 if an exception is thrown', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authenticate[0].innerHandle = () => { throw new Error('exception test'); };
|
||||
await agent.get('/').expect(500);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
|
||||
|
@ -319,6 +351,7 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
it('is not called if !requireAuthorization (non-/admin)', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/').auth('user', 'user-password').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
|
@ -327,6 +360,7 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('is not called if !requireAuthorization (/admin)', async function () {
|
||||
this.timeout(100);
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
|
@ -335,6 +369,7 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
it('defers if empty list returned', async function () {
|
||||
this.timeout(100);
|
||||
await agent.get('/').auth('user', 'user-password').expect(403);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
'preAuthorize_1',
|
||||
|
@ -344,6 +379,7 @@ describe(__filename, function () {
|
|||
'authorize_1']);
|
||||
});
|
||||
it('does not defer if return [true], 200', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authorize[0].innerHandle = () => [true];
|
||||
await agent.get('/').auth('user', 'user-password').expect(200);
|
||||
// Note: authorize_1 was not called because authorize_0 handled it.
|
||||
|
@ -354,6 +390,7 @@ describe(__filename, function () {
|
|||
'authorize_0']);
|
||||
});
|
||||
it('does not defer if return [false], 403', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authorize[0].innerHandle = (req) => [false];
|
||||
await agent.get('/').auth('user', 'user-password').expect(403);
|
||||
// Note: authorize_1 was not called because authorize_0 handled it.
|
||||
|
@ -364,6 +401,7 @@ describe(__filename, function () {
|
|||
'authorize_0']);
|
||||
});
|
||||
it('passes req.path in context', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authorize[0].checkContext = ({resource}) => {
|
||||
assert.equal(resource, '/');
|
||||
};
|
||||
|
@ -376,6 +414,7 @@ describe(__filename, function () {
|
|||
'authorize_1']);
|
||||
});
|
||||
it('returns 500 if an exception is thrown', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authorize[0].innerHandle = () => { throw new Error('exception test'); };
|
||||
await agent.get('/').auth('user', 'user-password').expect(500);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
|
@ -422,6 +461,7 @@ describe(__filename, function () {
|
|||
|
||||
// authn failure tests
|
||||
it('authn fail, no hooks handle -> 401', async function () {
|
||||
this.timeout(100);
|
||||
await agent.get('/').expect(401);
|
||||
assert(handlers.authnFailure.called);
|
||||
assert(!handlers.authzFailure.called);
|
||||
|
@ -435,6 +475,7 @@ describe(__filename, function () {
|
|||
assert(!handlers.authFailure.called);
|
||||
});
|
||||
it('authn fail, authFailure handles', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authFailure.shouldHandle = true;
|
||||
await agent.get('/').expect(200, 'authFailure');
|
||||
assert(handlers.authnFailure.called);
|
||||
|
@ -442,6 +483,7 @@ describe(__filename, function () {
|
|||
assert(handlers.authFailure.called);
|
||||
});
|
||||
it('authnFailure trumps authFailure', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authnFailure.shouldHandle = true;
|
||||
handlers.authFailure.shouldHandle = true;
|
||||
await agent.get('/').expect(200, 'authnFailure');
|
||||
|
@ -451,12 +493,14 @@ describe(__filename, function () {
|
|||
|
||||
// authz failure tests
|
||||
it('authz fail, no hooks handle -> 403', async function () {
|
||||
this.timeout(100);
|
||||
await agent.get('/').auth('user', 'user-password').expect(403);
|
||||
assert(!handlers.authnFailure.called);
|
||||
assert(handlers.authzFailure.called);
|
||||
assert(handlers.authFailure.called);
|
||||
});
|
||||
it('authz fail, authzFailure handles', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authzFailure.shouldHandle = true;
|
||||
await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure');
|
||||
assert(!handlers.authnFailure.called);
|
||||
|
@ -464,6 +508,7 @@ describe(__filename, function () {
|
|||
assert(!handlers.authFailure.called);
|
||||
});
|
||||
it('authz fail, authFailure handles', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authFailure.shouldHandle = true;
|
||||
await agent.get('/').auth('user', 'user-password').expect(200, 'authFailure');
|
||||
assert(!handlers.authnFailure.called);
|
||||
|
@ -471,6 +516,7 @@ describe(__filename, function () {
|
|||
assert(handlers.authFailure.called);
|
||||
});
|
||||
it('authzFailure trumps authFailure', async function () {
|
||||
this.timeout(100);
|
||||
handlers.authzFailure.shouldHandle = true;
|
||||
handlers.authFailure.shouldHandle = true;
|
||||
await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure');
|
||||
|
|
|
@ -3216,10 +3216,10 @@ function HTML(runner, options) {
|
|||
runner.on(EVENT_TEST_PASS, function(test) {
|
||||
var url = self.testURL(test);
|
||||
var markup =
|
||||
'<li class="test pass %e"><h2>%e<span class="duration">%ems</span> ' +
|
||||
'<li class="test pass %e"><h2>%e</h2><span class="duration">%ems</span> ' +
|
||||
'<a href="%s" class="replay">' +
|
||||
playIcon +
|
||||
'</a></h2></li>';
|
||||
'</a></li>';
|
||||
var el = fragment(markup, test.speed, test.title, test.duration, url);
|
||||
self.addCodeToggle(el, test.body);
|
||||
appendToStack(el);
|
||||
|
|
|
@ -102,11 +102,9 @@ body {
|
|||
}
|
||||
|
||||
#mocha .test.pass.medium .duration {
|
||||
background: #C09853;
|
||||
}
|
||||
|
||||
#mocha .test.pass.slow .duration {
|
||||
background: #B94A48;
|
||||
}
|
||||
|
||||
#mocha .test.pass::before {
|
||||
|
@ -122,19 +120,9 @@ body {
|
|||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
padding: 2px 5px;
|
||||
color: white;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass.fast .duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha .test.pending {
|
||||
|
|
|
@ -69,7 +69,7 @@ $(() => {
|
|||
}, 60000 * 3);
|
||||
|
||||
const medium = test.slow() / 2;
|
||||
test.speed = test.duration > test.slow()
|
||||
test.speed = test.duratoin > test.slow()
|
||||
? 'slow'
|
||||
: test.duration > medium
|
||||
? 'medium'
|
||||
|
|
|
@ -10,6 +10,7 @@ describe('All the alphabet works n stuff', function () {
|
|||
});
|
||||
|
||||
it('when you enter any char it appears right', function (done) {
|
||||
this.timeout(250);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element out of the inner iframe
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('author of pad edition', function () {
|
|||
'token=foo;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
|
||||
|
||||
helper.newPad(done, padId);
|
||||
}, 1000);
|
||||
}, 10000);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -60,16 +60,20 @@ describe('author of pad edition', function () {
|
|||
|
||||
// author 2 makes some changes on the pad
|
||||
it('marks only the new content as changes of the second user on a regular line', function (done) {
|
||||
this.timeout(1000);
|
||||
changeLineAndCheckOnlyThatChangeIsFromThisAuthor(REGULAR_LINE, 'x', done);
|
||||
});
|
||||
|
||||
|
||||
it('marks only the new content as changes of the second user on a ' +
|
||||
'line with ordered list', function (done) {
|
||||
this.timeout(1000);
|
||||
changeLineAndCheckOnlyThatChangeIsFromThisAuthor(LINE_WITH_ORDERED_LIST, 'y', done);
|
||||
});
|
||||
|
||||
it('marks only the new content as changes of the second user on ' +
|
||||
'a line with unordered list', function (done) {
|
||||
this.timeout(1000);
|
||||
changeLineAndCheckOnlyThatChangeIsFromThisAuthor(LINE_WITH_UNORDERED_LIST, 'z', done);
|
||||
});
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('bold button', function () {
|
|||
});
|
||||
|
||||
it('makes text bold on click', function (done) {
|
||||
this.timeout();
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -36,6 +37,7 @@ describe('bold button', function () {
|
|||
});
|
||||
|
||||
it('makes text bold on keypress', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element out of the inner iframe
|
||||
|
|
|
@ -9,7 +9,7 @@ describe('change user color', function () {
|
|||
|
||||
it('Color picker matches original color and remembers the user color' +
|
||||
' after a refresh', function (done) {
|
||||
this.timeout(60000);
|
||||
this.timeout(10000);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// click on the settings button to make settings visible
|
||||
|
@ -63,6 +63,7 @@ describe('change user color', function () {
|
|||
});
|
||||
|
||||
it('Own user color is shown when you enter a chat', function (done) {
|
||||
this.timeout(1000);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
const $colorOption = helper.padChrome$('#options-colorscheck');
|
||||
|
|
|
@ -7,6 +7,7 @@ describe('change username value', function () {
|
|||
});
|
||||
|
||||
it('Remembers the user name after a refresh', async function () {
|
||||
this.timeout(500);
|
||||
helper.toggleUserList();
|
||||
helper.setUserName('😃');
|
||||
|
||||
|
@ -21,6 +22,7 @@ describe('change username value', function () {
|
|||
});
|
||||
|
||||
it('Own user name is shown when you enter a chat', async function () {
|
||||
this.timeout(1000);
|
||||
helper.toggleUserList();
|
||||
helper.setUserName('😃');
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ describe('Chat messages and UI', function () {
|
|||
|
||||
it('opens chat, sends a message, makes sure it exists ' +
|
||||
'on the page and hides chat', async function () {
|
||||
this.timeout(3000);
|
||||
|
||||
const chatValue = 'JohnMcLear';
|
||||
|
||||
await helper.showChat();
|
||||
|
@ -30,6 +32,7 @@ describe('Chat messages and UI', function () {
|
|||
});
|
||||
|
||||
it("makes sure that an empty message can't be sent", async function () {
|
||||
this.timeout(3000);
|
||||
const chatValue = 'mluto';
|
||||
|
||||
await helper.showChat();
|
||||
|
@ -50,6 +53,7 @@ describe('Chat messages and UI', function () {
|
|||
|
||||
it('makes chat stick to right side of the screen via settings, ' +
|
||||
'remove sticky via settings, close it', async function () {
|
||||
this.timeout(5000);
|
||||
await helper.showSettings();
|
||||
|
||||
await helper.enableStickyChatviaSettings();
|
||||
|
@ -67,6 +71,8 @@ describe('Chat messages and UI', function () {
|
|||
|
||||
it('makes chat stick to right side of the screen via icon on the top' +
|
||||
' right, remove sticky via icon, close it', async function () {
|
||||
this.timeout(5000);
|
||||
|
||||
await helper.showChat();
|
||||
|
||||
await helper.enableStickyChatviaIcon();
|
||||
|
@ -108,9 +114,9 @@ describe('Chat messages and UI', function () {
|
|||
done();
|
||||
},
|
||||
});
|
||||
}, 1000);
|
||||
}, );
|
||||
},
|
||||
});
|
||||
}, 1000);
|
||||
}, 3000);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,19 +4,18 @@ describe('chat-load-messages', function () {
|
|||
let padName;
|
||||
|
||||
it('creates a pad', function (done) {
|
||||
this.timeout(20000);
|
||||
padName = helper.newPad(done);
|
||||
this.timeout(60000);
|
||||
});
|
||||
|
||||
it('adds a lot of messages', function (done) {
|
||||
this.timeout(10000);
|
||||
const chrome$ = helper.padChrome$;
|
||||
const chatButton = chrome$('#chaticon');
|
||||
chatButton.click();
|
||||
const chatInput = chrome$('#chatinput');
|
||||
const chatText = chrome$('#chattext');
|
||||
|
||||
this.timeout(60000);
|
||||
|
||||
const messages = 140;
|
||||
for (let i = 1; i <= messages; i++) {
|
||||
let num = `${i}`;
|
||||
|
@ -32,6 +31,7 @@ describe('chat-load-messages', function () {
|
|||
});
|
||||
|
||||
it('checks initial message count', function (done) {
|
||||
this.timeout(1000);
|
||||
let chatText;
|
||||
const expectedCount = 101;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
@ -47,6 +47,7 @@ describe('chat-load-messages', function () {
|
|||
});
|
||||
|
||||
it('loads more messages', function (done) {
|
||||
this.timeout(3000);
|
||||
const expectedCount = 122;
|
||||
const chrome$ = helper.padChrome$;
|
||||
const chatButton = chrome$('#chaticon');
|
||||
|
@ -62,6 +63,7 @@ describe('chat-load-messages', function () {
|
|||
});
|
||||
|
||||
it('checks for button vanishing', function (done) {
|
||||
this.timeout(2000);
|
||||
const expectedDisplay = 'none';
|
||||
const chrome$ = helper.padChrome$;
|
||||
const chatButton = chrome$('#chaticon');
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('clear authorship colors button', function () {
|
|||
});
|
||||
|
||||
it('makes text clear authorship colors', function (done) {
|
||||
this.timeout(1500);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -28,7 +29,8 @@ describe('clear authorship colors button', function () {
|
|||
$firstTextElement.sendkeys('{rightarrow}');
|
||||
|
||||
// wait until we have the full value available
|
||||
helper.waitFor(() => inner$('div span').first().attr('class').indexOf('author') !== -1
|
||||
helper.waitFor(
|
||||
() => inner$('div span').first().attr('class').indexOf('author') !== -1
|
||||
).done(() => {
|
||||
// IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship
|
||||
inner$('div').first().focus();
|
||||
|
@ -55,6 +57,7 @@ describe('clear authorship colors button', function () {
|
|||
});
|
||||
|
||||
it("makes text clear authorship colors and checks it can't be undone", function (done) {
|
||||
this.timeout(1500);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ describe('delete keystroke', function () {
|
|||
});
|
||||
|
||||
it('makes text delete', function (done) {
|
||||
this.timeout(50);
|
||||
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element out of the inner iframe
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
// WARNING: drag and drop is only simulated on these tests, manual testing might also be necessary
|
||||
// WARNING: drag and drop is only simulated on these tests
|
||||
// so manual testing might also be necessary
|
||||
describe('drag and drop', function () {
|
||||
before(function (done) {
|
||||
helper.newPad(() => {
|
||||
|
@ -29,6 +30,7 @@ describe('drag and drop', function () {
|
|||
});
|
||||
|
||||
it('moves text back to its original place', function (done) {
|
||||
this.timeout(50);
|
||||
// test text was removed from drop target
|
||||
const $targetLine = getLine(TARGET_LINE);
|
||||
expect($targetLine.text()).to.be('Target line []');
|
||||
|
@ -64,6 +66,7 @@ describe('drag and drop', function () {
|
|||
});
|
||||
|
||||
it('moves text back to its original place', function (done) {
|
||||
this.timeout(50);
|
||||
// test text was removed from drop target
|
||||
const $targetLine = getLine(TARGET_LINE);
|
||||
expect($targetLine.text()).to.be('Target line []');
|
||||
|
|
|
@ -57,6 +57,7 @@ describe('embed links', function () {
|
|||
|
||||
describe('the share link', function () {
|
||||
it('is the actual pad url', function (done) {
|
||||
this.timeout(50);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// open share dropdown
|
||||
|
@ -73,6 +74,7 @@ describe('embed links', function () {
|
|||
|
||||
describe('the embed as iframe code', function () {
|
||||
it('is an iframe with the the correct url parameters and correct size', function (done) {
|
||||
this.timeout(50);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// open share dropdown
|
||||
|
@ -96,6 +98,7 @@ describe('embed links', function () {
|
|||
|
||||
describe('the share link', function () {
|
||||
it('shows a read only url', function (done) {
|
||||
this.timeout(50);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// open share dropdown
|
||||
|
@ -114,6 +117,7 @@ describe('embed links', function () {
|
|||
|
||||
describe('the embed as iframe code', function () {
|
||||
it('is an iframe with the the correct url parameters and correct size', function (done) {
|
||||
this.timeout(50);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// open share dropdown
|
||||
|
|
|
@ -8,6 +8,8 @@ describe('enter keystroke', function () {
|
|||
});
|
||||
|
||||
it('creates a new line & puts cursor onto a new line', function (done) {
|
||||
this.timeout(2000);
|
||||
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element out of the inner iframe
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('font select', function () {
|
|||
});
|
||||
|
||||
it('makes text RobotoMono', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('indentation button', function () {
|
|||
});
|
||||
|
||||
it('indent text with keypress', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element out of the inner iframe
|
||||
|
@ -24,6 +25,7 @@ describe('indentation button', function () {
|
|||
});
|
||||
|
||||
it('indent text with button', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -34,6 +36,7 @@ describe('indentation button', function () {
|
|||
});
|
||||
|
||||
it('keeps the indent on enter for the new line', function (done) {
|
||||
this.timeout(1200);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -59,6 +62,7 @@ describe('indentation button', function () {
|
|||
|
||||
it('indents text with spaces on enter if previous line ends ' +
|
||||
"with ':', '[', '(', or '{'", function (done) {
|
||||
this.timeout(1200);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// type a bit, make a line break and type again
|
||||
|
@ -110,6 +114,7 @@ describe('indentation button', function () {
|
|||
|
||||
it('appends indentation to the indent of previous line if previous line ends ' +
|
||||
"with ':', '[', '(', or '{'", function (done) {
|
||||
this.timeout(1200);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// type a bit, make a line break and type again
|
||||
|
@ -135,6 +140,7 @@ describe('indentation button', function () {
|
|||
|
||||
it("issue #2772 shows '*' when multiple indented lines " +
|
||||
' receive a style and are outdented', async function () {
|
||||
this.timeout(1200);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('italic some text', function () {
|
|||
});
|
||||
|
||||
it('makes text italic using button', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -21,7 +22,6 @@ describe('italic some text', function () {
|
|||
const $boldButton = chrome$('.buttonicon-italic');
|
||||
$boldButton.click();
|
||||
|
||||
// ace creates a new dom element when you press a button, just get the first text element again
|
||||
const $newFirstTextElement = inner$('div').first();
|
||||
|
||||
// is there a <i> element now?
|
||||
|
@ -37,6 +37,7 @@ describe('italic some text', function () {
|
|||
});
|
||||
|
||||
it('makes text italic using keypress', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element out of the inner iframe
|
||||
|
@ -50,7 +51,6 @@ describe('italic some text', function () {
|
|||
e.which = 105; // i
|
||||
inner$('#innerdocbody').trigger(e);
|
||||
|
||||
// ace creates a new dom element when you press a button, just get the first text element again
|
||||
const $newFirstTextElement = inner$('div').first();
|
||||
|
||||
// is there a <i> element now?
|
||||
|
|
|
@ -16,6 +16,7 @@ describe('Language select and change', function () {
|
|||
|
||||
// Destroy language cookies
|
||||
it('makes text german', function (done) {
|
||||
this.timeout(1000);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// click on the settings button to make settings visible
|
||||
|
@ -45,6 +46,7 @@ describe('Language select and change', function () {
|
|||
});
|
||||
|
||||
it('makes text English', function (done) {
|
||||
this.timeout(1000);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// click on the settings button to make settings visible
|
||||
|
@ -75,6 +77,7 @@ describe('Language select and change', function () {
|
|||
});
|
||||
|
||||
it('changes direction when picking an rtl lang', function (done) {
|
||||
this.timeout(1000);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// click on the settings button to make settings visible
|
||||
|
@ -99,6 +102,7 @@ describe('Language select and change', function () {
|
|||
});
|
||||
|
||||
it('changes direction when picking an ltr lang', function (done) {
|
||||
this.timeout(300);
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
// click on the settings button to make settings visible
|
||||
|
|
|
@ -49,4 +49,10 @@ describe('author of pad edition', function () {
|
|||
expect(hasAuthorClass).to.be(false);
|
||||
done();
|
||||
};
|
||||
|
||||
// author 2 makes some changes on the pad
|
||||
it('Clears Authorship by second user', function (done) {
|
||||
this.timeout(100);
|
||||
clearAuthorship(done);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('assign ordered list', function () {
|
|||
});
|
||||
|
||||
it('inserts ordered list text', function (done) {
|
||||
this.timeout(200);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -25,6 +26,7 @@ describe('assign ordered list', function () {
|
|||
});
|
||||
|
||||
it('inserts unordered list', function (done) {
|
||||
this.timeout(50);
|
||||
helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1).done(done);
|
||||
});
|
||||
});
|
||||
|
@ -36,6 +38,7 @@ describe('assign ordered list', function () {
|
|||
});
|
||||
|
||||
it('does not insert unordered list', function (done) {
|
||||
this.timeout(3000);
|
||||
helper.waitFor(
|
||||
() => helper.padInner$('div').first().find('ol li').length === 1).done(() => {
|
||||
expect().fail(() => 'Unordered list inserted, should ignore shortcut');
|
||||
|
@ -54,6 +57,7 @@ describe('assign ordered list', function () {
|
|||
});
|
||||
|
||||
it('inserts unordered list', function (done) {
|
||||
this.timeout(200);
|
||||
helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1).done(done);
|
||||
});
|
||||
});
|
||||
|
@ -65,6 +69,7 @@ describe('assign ordered list', function () {
|
|||
});
|
||||
|
||||
it('does not insert unordered list', function (done) {
|
||||
this.timeout(3000);
|
||||
helper.waitFor(
|
||||
() => helper.padInner$('div').first().find('ol li').length === 1).done(() => {
|
||||
expect().fail(() => 'Unordered list inserted, should ignore shortcut');
|
||||
|
@ -127,6 +132,7 @@ describe('Pressing Tab in an OL increases and decreases indentation', function (
|
|||
});
|
||||
|
||||
it('indent and de-indent list item with keypress', function (done) {
|
||||
this.timeout(200);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -162,6 +168,7 @@ describe('Pressing indent/outdent button in an OL increases and ' +
|
|||
});
|
||||
|
||||
it('indent and de-indent list item with indent button', function (done) {
|
||||
this.timeout(1000);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ describe('Pad modal', function () {
|
|||
});
|
||||
|
||||
it('disables editor', function (done) {
|
||||
this.timeout(20);
|
||||
expect(isEditorDisabled()).to.be(true);
|
||||
|
||||
done();
|
||||
|
@ -29,6 +30,7 @@ describe('Pad modal', function () {
|
|||
});
|
||||
|
||||
it('does not close the modal', function (done) {
|
||||
this.timeout(20);
|
||||
const $modal = helper.padChrome$(MODAL_SELECTOR);
|
||||
const modalIsVisible = $modal.hasClass('popup-show');
|
||||
|
||||
|
@ -44,6 +46,7 @@ describe('Pad modal', function () {
|
|||
});
|
||||
|
||||
it('does not close the modal', function (done) {
|
||||
this.timeout(20);
|
||||
const $modal = helper.padChrome$(MODAL_SELECTOR);
|
||||
const modalIsVisible = $modal.hasClass('popup-show');
|
||||
|
||||
|
@ -78,6 +81,7 @@ describe('Pad modal', function () {
|
|||
});
|
||||
|
||||
it('closes the modal', function (done) {
|
||||
this.timeout(20);
|
||||
expect(isModalOpened(MODAL_SELECTOR)).to.be(false);
|
||||
done();
|
||||
});
|
||||
|
@ -89,6 +93,7 @@ describe('Pad modal', function () {
|
|||
});
|
||||
|
||||
it('closes the modal', function (done) {
|
||||
this.timeout(20);
|
||||
expect(isModalOpened(MODAL_SELECTOR)).to.be(false);
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ describe('undo button then redo button', function () {
|
|||
});
|
||||
|
||||
it('redo some typing with button', function (done) {
|
||||
this.timeout(200);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -34,6 +35,7 @@ describe('undo button then redo button', function () {
|
|||
});
|
||||
|
||||
it('redo some typing with keypress', function (done) {
|
||||
this.timeout(200);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element inside the editable space
|
||||
|
|
|
@ -11,7 +11,7 @@ describe('scrolls to line', function () {
|
|||
});
|
||||
|
||||
it('Scrolls down to Line 4', async function () {
|
||||
this.timeout(10000);
|
||||
this.timeout(100);
|
||||
const chrome$ = helper.padChrome$;
|
||||
await helper.waitForPromise(() => {
|
||||
const topOffset = parseInt(chrome$('iframe').first('iframe')
|
||||
|
@ -32,7 +32,7 @@ describe('doesnt break on weird hash input', function () {
|
|||
});
|
||||
|
||||
it('Does NOT change scroll', async function () {
|
||||
this.timeout(10000);
|
||||
this.timeout(100);
|
||||
const chrome$ = helper.padChrome$;
|
||||
await helper.waitForPromise(() => {
|
||||
const topOffset = parseInt(chrome$('iframe').first('iframe')
|
||||
|
|
|
@ -42,12 +42,14 @@ describe('select formatting buttons when selection has style applied', function
|
|||
|
||||
const testIfFormattingButtonIsDeselected = function (style) {
|
||||
it(`deselects the ${style} button`, function (done) {
|
||||
this.timeout(50);
|
||||
helper.waitFor(() => isButtonSelected(style) === false).done(done);
|
||||
});
|
||||
};
|
||||
|
||||
const testIfFormattingButtonIsSelected = function (style) {
|
||||
it(`selects the ${style} button`, function (done) {
|
||||
this.timeout(50);
|
||||
helper.waitFor(() => isButtonSelected(style)).done(done);
|
||||
});
|
||||
};
|
||||
|
@ -135,6 +137,7 @@ describe('select formatting buttons when selection has style applied', function
|
|||
});
|
||||
|
||||
it('selects the style button', function (done) {
|
||||
this.timeout(50);
|
||||
expect(isButtonSelected(style)).to.be(true);
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('strikethrough button', function () {
|
|||
});
|
||||
|
||||
it('makes text strikethrough', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -21,7 +22,6 @@ describe('strikethrough button', function () {
|
|||
const $strikethroughButton = chrome$('.buttonicon-strikethrough');
|
||||
$strikethroughButton.click();
|
||||
|
||||
// ace creates a new dom element when you press a button, just get the first text element again
|
||||
const $newFirstTextElement = inner$('div').first();
|
||||
|
||||
// is there a <i> element now?
|
||||
|
|
|
@ -9,6 +9,7 @@ describe('timeslider follow', function () {
|
|||
// TODO needs test if content is also followed, when user a makes edits
|
||||
// while user b is in the timeslider
|
||||
it("content as it's added to timeslider", async function () {
|
||||
this.timeout(0); // JM TO DO
|
||||
// send 6 revisions
|
||||
const revs = 6;
|
||||
const message = 'a\n\n\n\n\n\n\n\n\n\n';
|
||||
|
|
|
@ -9,7 +9,10 @@ describe('timeslider', function () {
|
|||
/**
|
||||
* @todo test authorsList
|
||||
*/
|
||||
it("Shows a date/time in the timeslider and make sure it doesn't include NaN", async function () {
|
||||
|
||||
it('Shows a correctly formatted date and time', async function () {
|
||||
this.timeout(12000);
|
||||
|
||||
// make some changes to produce 3 revisions
|
||||
const revs = 3;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ describe('timeslider', function () {
|
|||
});
|
||||
|
||||
it('Makes sure the export URIs are as expected when the padID is numeric', async function () {
|
||||
this.timeout(6000);
|
||||
|
||||
await helper.edit('a\n');
|
||||
|
||||
await helper.gotoTimeslider(1);
|
||||
|
|
|
@ -7,7 +7,8 @@ describe('timeslider', function () {
|
|||
this.timeout(60000);
|
||||
});
|
||||
|
||||
it('loads adds a hundred revisions', function (done) { // passes
|
||||
it('loads adds a hundred revisions', function (done) {
|
||||
this.timeout(100000);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -110,8 +111,8 @@ describe('timeslider', function () {
|
|||
}, revs * timePerRev);
|
||||
});
|
||||
it('jumps to a revision given in the url', function (done) {
|
||||
const inner$ = helper.padInner$;
|
||||
this.timeout(40000);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// wait for the text to be loaded
|
||||
helper.waitFor(() => inner$('body').text().length !== 0, 10000).always(() => {
|
||||
|
@ -132,6 +133,7 @@ describe('timeslider', function () {
|
|||
return lenOkay && colorOkay;
|
||||
}, 10000).always(() => {
|
||||
// go to timeslider with a specific revision set
|
||||
|
||||
$('#iframe-container iframe').attr('src',
|
||||
`${$('#iframe-container iframe').attr('src')}/timeslider#0`);
|
||||
|
||||
|
@ -154,6 +156,7 @@ describe('timeslider', function () {
|
|||
});
|
||||
|
||||
it('checks the export url', function (done) {
|
||||
this.timeout(6000);
|
||||
const inner$ = helper.padInner$;
|
||||
this.timeout(11000);
|
||||
inner$('div').first().sendkeys('a');
|
||||
|
|
|
@ -7,6 +7,7 @@ describe('undo button', function () {
|
|||
});
|
||||
|
||||
it('undo some typing by clicking undo button', function (done) {
|
||||
this.timeout(150);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -31,6 +32,7 @@ describe('undo button', function () {
|
|||
});
|
||||
|
||||
it('undo some typing using a keypress', function (done) {
|
||||
this.timeout(150);
|
||||
const inner$ = helper.padInner$;
|
||||
|
||||
// get the first text element inside the editable space
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('assign unordered list', function () {
|
|||
});
|
||||
|
||||
it('insert unordered list text then removes by outdent', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
const originalText = inner$('div').first().text();
|
||||
|
@ -34,6 +35,7 @@ describe('assign unordered list', function () {
|
|||
});
|
||||
|
||||
describe('unassign unordered list', function () {
|
||||
this.timeout(100);
|
||||
// create a new pad before each test run
|
||||
beforeEach(function (cb) {
|
||||
helper.newPad(cb);
|
||||
|
@ -41,6 +43,7 @@ describe('unassign unordered list', function () {
|
|||
});
|
||||
|
||||
it('insert unordered list text then remove by clicking list again', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
const originalText = inner$('div').first().text();
|
||||
|
@ -76,6 +79,7 @@ describe('keep unordered list on enter key', function () {
|
|||
});
|
||||
|
||||
it('Keeps the unordered list on enter for the new line', function (done) {
|
||||
this.timeout(1000);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -100,6 +104,7 @@ describe('keep unordered list on enter key', function () {
|
|||
});
|
||||
|
||||
describe('Pressing Tab in an UL increases and decreases indentation', function () {
|
||||
this.timeout(100);
|
||||
// create a new pad before each test run
|
||||
beforeEach(function (cb) {
|
||||
helper.newPad(cb);
|
||||
|
@ -107,6 +112,7 @@ describe('Pressing Tab in an UL increases and decreases indentation', function (
|
|||
});
|
||||
|
||||
it('indent and de-indent list item with keypress', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
@ -141,6 +147,7 @@ describe('Pressing indent/outdent button in an UL increases and decreases indent
|
|||
});
|
||||
|
||||
it('indent and de-indent list item with indent button', function (done) {
|
||||
this.timeout(100);
|
||||
const inner$ = helper.padInner$;
|
||||
const chrome$ = helper.padChrome$;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ describe('urls', function () {
|
|||
describe('entering a URL makes a link', function () {
|
||||
for (const url of ['https://etherpad.org', 'www.etherpad.org']) {
|
||||
it(url, async function () {
|
||||
this.timeout(5000);
|
||||
const url = 'https://etherpad.org';
|
||||
await helper.edit(url);
|
||||
await helper.waitForPromise(() => txt().find('a').length === 1, 2000);
|
||||
|
@ -34,6 +35,7 @@ describe('urls', function () {
|
|||
for (const char of '-:@_.,~%+/?=&#!;()$\'*') {
|
||||
const url = `https://etherpad.org/${char}foo`;
|
||||
it(url, async function () {
|
||||
this.timeout(5000);
|
||||
await helper.edit(url);
|
||||
await helper.waitForPromise(() => txt().find('a').length === 1);
|
||||
const link = txt().find('a');
|
||||
|
@ -48,6 +50,7 @@ describe('urls', function () {
|
|||
const want = 'https://etherpad.org';
|
||||
const input = want + char;
|
||||
it(input, async function () {
|
||||
this.timeout(5000);
|
||||
await helper.edit(input);
|
||||
await helper.waitForPromise(() => txt().find('a').length === 1);
|
||||
const link = txt().find('a');
|
||||
|
|
|
@ -61,9 +61,8 @@ describe('Automatic pad reload on Force Reconnect message', function () {
|
|||
});
|
||||
|
||||
it('reloads the pad', function (done) {
|
||||
helper.waitFor(() => padWasReloaded, 5000).done(done);
|
||||
|
||||
this.timeout(5000);
|
||||
helper.waitFor(() => padWasReloaded, 5000).done(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue