tests: timeouts for tests (#4773)

This commit is contained in:
John McLear 2021-02-13 19:00:06 +00:00 committed by GitHub
parent f9ec49d7ac
commit e585d321f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 368 additions and 4 deletions

View file

@ -43,6 +43,7 @@ describe(__filename, function () {
}); });
it('can obtain valid openapi definition document', async function () { it('can obtain valid openapi definition document', async function () {
this.timeout(15000);
await agent.get('/api/openapi.json') await agent.get('/api/openapi.json')
.expect(200) .expect(200)
.expect((res) => { .expect((res) => {
@ -56,6 +57,7 @@ describe(__filename, function () {
}); });
it('supports jsonp calls', async function () { it('supports jsonp calls', async function () {
this.timeout(150);
await agent.get(`${endPoint('createPad')}&jsonp=jsonp_1&padID=${testPadId}`) await agent.get(`${endPoint('createPad')}&jsonp=jsonp_1&padID=${testPadId}`)
.expect(200) .expect(200)
.expect('Content-Type', /javascript/) .expect('Content-Type', /javascript/)

View file

@ -19,6 +19,7 @@ const testPadId = makeid();
describe(__filename, function () { describe(__filename, function () {
describe('Connectivity For Character Encoding', function () { describe('Connectivity For Character Encoding', function () {
it('can connect', function (done) { it('can connect', function (done) {
this.timeout(250);
api.get('/api/') api.get('/api/')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200, done); .expect(200, done);
@ -26,6 +27,7 @@ describe(__filename, function () {
}); });
describe('API Versioning', function () { describe('API Versioning', function () {
this.timeout(150);
it('finds the version tag', function (done) { it('finds the version tag', function (done) {
api.get('/api/') api.get('/api/')
.expect((res) => { .expect((res) => {
@ -39,6 +41,7 @@ describe(__filename, function () {
describe('Permission', function () { describe('Permission', function () {
it('errors with invalid APIKey', function (done) { it('errors with invalid APIKey', function (done) {
this.timeout(150);
// This is broken because Etherpad doesn't handle HTTP codes properly see #2343 // 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 // If your APIKey is password you deserve to fail all tests anyway
const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`; const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`;
@ -49,6 +52,7 @@ describe(__filename, function () {
describe('createPad', function () { describe('createPad', function () {
it('creates a new Pad', function (done) { it('creates a new Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('createPad')}&padID=${testPadId}`) api.get(`${endPoint('createPad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to create new Pad'); if (res.body.code !== 0) throw new Error('Unable to create new Pad');
@ -60,6 +64,7 @@ describe(__filename, function () {
describe('setHTML', function () { describe('setHTML', function () {
it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function (done) { 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) => { fs.readFile('tests/backend/specs/api/emojis.html', 'utf8', (err, html) => {
api.post(endPoint('setHTML')) api.post(endPoint('setHTML'))
.send({ .send({
@ -77,6 +82,7 @@ describe(__filename, function () {
describe('getHTML', function () { describe('getHTML', function () {
it('get the HTML of Pad with emojis', function (done) { it('get the HTML of Pad with emojis', function (done) {
this.timeout(400);
api.get(`${endPoint('getHTML')}&padID=${testPadId}`) api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.html.indexOf('&#127484') === -1) { if (res.body.data.html.indexOf('&#127484') === -1) {

View file

@ -35,6 +35,7 @@ describe(__filename, function () {
*/ */
describe('createPad', function () { describe('createPad', function () {
this.timeout(400);
it('creates a new Pad', function (done) { it('creates a new Pad', function (done) {
api.get(`${endPoint('createPad')}&padID=${padID}`) api.get(`${endPoint('createPad')}&padID=${padID}`)
.expect((res) => { .expect((res) => {
@ -46,6 +47,7 @@ describe(__filename, function () {
}); });
describe('createAuthor', function () { describe('createAuthor', function () {
this.timeout(100);
it('Creates an author with a name set', function (done) { it('Creates an author with a name set', function (done) {
api.get(endPoint('createAuthor')) api.get(endPoint('createAuthor'))
.expect((res) => { .expect((res) => {
@ -58,6 +60,7 @@ describe(__filename, function () {
}); });
describe('appendChatMessage', function () { describe('appendChatMessage', function () {
this.timeout(100);
it('Adds a chat message to the pad', function (done) { it('Adds a chat message to the pad', function (done) {
api.get(`${endPoint('appendChatMessage')}&padID=${padID}&text=blalblalbha&authorID=${authorID}&time=${timestamp}`) api.get(`${endPoint('appendChatMessage')}&padID=${padID}&text=blalblalbha&authorID=${authorID}&time=${timestamp}`)
.expect((res) => { .expect((res) => {
@ -70,6 +73,7 @@ describe(__filename, function () {
describe('getChatHead', function () { describe('getChatHead', function () {
this.timeout(100);
it('Gets the head of chat', function (done) { it('Gets the head of chat', function (done) {
api.get(`${endPoint('getChatHead')}&padID=${padID}`) api.get(`${endPoint('getChatHead')}&padID=${padID}`)
.expect((res) => { .expect((res) => {
@ -83,6 +87,7 @@ describe(__filename, function () {
}); });
describe('getChatHistory', function () { describe('getChatHistory', function () {
this.timeout(40);
it('Gets Chat History of a Pad', function (done) { it('Gets Chat History of a Pad', function (done) {
api.get(`${endPoint('getChatHistory')}&padID=${padID}`) api.get(`${endPoint('getChatHistory')}&padID=${padID}`)
.expect((res) => { .expect((res) => {

View file

@ -236,6 +236,7 @@ describe(__filename, function () {
}); });
} }
it('createPad', function (done) { it('createPad', function (done) {
this.timeout(200);
api.get(`${endPoint('createPad')}&padID=${testPadId}`) api.get(`${endPoint('createPad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to create new Pad'); if (res.body.code !== 0) throw new Error('Unable to create new Pad');
@ -245,6 +246,7 @@ describe(__filename, function () {
}); });
it('setHTML', function (done) { it('setHTML', function (done) {
this.timeout(150);
api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${encodeURIComponent(test.input)}`) api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${encodeURIComponent(test.input)}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error(`Error:${testName}`); if (res.body.code !== 0) throw new Error(`Error:${testName}`);
@ -254,6 +256,7 @@ describe(__filename, function () {
}); });
it('getHTML', function (done) { it('getHTML', function (done) {
this.timeout(150);
api.get(`${endPoint('getHTML')}&padID=${testPadId}`) api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
const gotHtml = res.body.data.html; const gotHtml = res.body.data.html;
@ -277,6 +280,7 @@ describe(__filename, function () {
}); });
it('getText', function (done) { it('getText', function (done) {
this.timeout(100);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
const gotText = res.body.data.text; const gotText = res.body.data.text;

View file

@ -26,10 +26,12 @@ const testPadId = makeid();
const testPadIdEnc = encodeURIComponent(testPadId); const testPadIdEnc = encodeURIComponent(testPadId);
describe(__filename, function () { describe(__filename, function () {
this.timeout(45000);
before(async function () { agent = await common.init(); }); before(async function () { agent = await common.init(); });
describe('Connectivity', function () { describe('Connectivity', function () {
it('can connect', async function () { it('can connect', async function () {
this.timeout(250);
await agent.get('/api/') await agent.get('/api/')
.expect(200) .expect(200)
.expect('Content-Type', /json/); .expect('Content-Type', /json/);
@ -38,6 +40,7 @@ describe(__filename, function () {
describe('API Versioning', function () { describe('API Versioning', function () {
it('finds the version tag', async function () { it('finds the version tag', async function () {
this.timeout(250);
await agent.get('/api/') await agent.get('/api/')
.expect(200) .expect(200)
.expect((res) => assert(res.body.currentVersion)); .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 () { it('creates a new Pad, imports content to it, checks that content', async function () {
this.timeout(500);
await agent.get(`${endPoint('createPad')}&padID=${testPadId}`) await agent.get(`${endPoint('createPad')}&padID=${testPadId}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .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 () { 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}`) const ro = await agent.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`)
.expect(200) .expect(200)
.expect((res) => assert.ok(JSON.parse(res.text).data.readOnlyID)); .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.. // For some reason word import does not work in testing..
// TODO: fix support for .doc files.. // TODO: fix support for .doc files..
it('Tries to import .doc that uses soffice or abiword', async function () { it('Tries to import .doc that uses soffice or abiword', async function () {
this.timeout(10000);
await agent.post(`/p/${testPadId}/import`) await agent.post(`/p/${testPadId}/import`)
.attach('file', wordDoc, {filename: '/test.doc', contentType: 'application/msword'}) .attach('file', wordDoc, {filename: '/test.doc', contentType: 'application/msword'})
.expect(200) .expect(200)
@ -139,6 +145,7 @@ describe(__filename, function () {
}); });
it('exports DOC', async function () { it('exports DOC', async function () {
this.timeout(3000);
await agent.get(`/p/${testPadId}/export/doc`) await agent.get(`/p/${testPadId}/export/doc`)
.buffer(true).parse(superagent.parse['application/octet-stream']) .buffer(true).parse(superagent.parse['application/octet-stream'])
.expect(200) .expect(200)
@ -146,6 +153,7 @@ describe(__filename, function () {
}); });
it('Tries to import .docx that uses soffice or abiword', async function () { it('Tries to import .docx that uses soffice or abiword', async function () {
this.timeout(3000);
await agent.post(`/p/${testPadId}/import`) await agent.post(`/p/${testPadId}/import`)
.attach('file', wordXDoc, { .attach('file', wordXDoc, {
filename: '/test.docx', filename: '/test.docx',
@ -157,6 +165,7 @@ describe(__filename, function () {
}); });
it('exports DOC from imported DOCX', async function () { it('exports DOC from imported DOCX', async function () {
this.timeout(3000);
await agent.get(`/p/${testPadId}/export/doc`) await agent.get(`/p/${testPadId}/export/doc`)
.buffer(true).parse(superagent.parse['application/octet-stream']) .buffer(true).parse(superagent.parse['application/octet-stream'])
.expect(200) .expect(200)
@ -164,6 +173,7 @@ describe(__filename, function () {
}); });
it('Tries to import .pdf that uses soffice or abiword', async function () { it('Tries to import .pdf that uses soffice or abiword', async function () {
this.timeout(3000);
await agent.post(`/p/${testPadId}/import`) await agent.post(`/p/${testPadId}/import`)
.attach('file', pdfDoc, {filename: '/test.pdf', contentType: 'application/pdf'}) .attach('file', pdfDoc, {filename: '/test.pdf', contentType: 'application/pdf'})
.expect(200) .expect(200)
@ -171,6 +181,7 @@ describe(__filename, function () {
}); });
it('exports PDF', async function () { it('exports PDF', async function () {
this.timeout(3000);
await agent.get(`/p/${testPadId}/export/pdf`) await agent.get(`/p/${testPadId}/export/pdf`)
.buffer(true).parse(superagent.parse['application/octet-stream']) .buffer(true).parse(superagent.parse['application/octet-stream'])
.expect(200) .expect(200)
@ -178,6 +189,7 @@ describe(__filename, function () {
}); });
it('Tries to import .odt that uses soffice or abiword', async function () { it('Tries to import .odt that uses soffice or abiword', async function () {
this.timeout(3000);
await agent.post(`/p/${testPadId}/import`) await agent.post(`/p/${testPadId}/import`)
.attach('file', odtDoc, {filename: '/test.odt', contentType: 'application/odt'}) .attach('file', odtDoc, {filename: '/test.odt', contentType: 'application/odt'})
.expect(200) .expect(200)
@ -185,6 +197,7 @@ describe(__filename, function () {
}); });
it('exports ODT', async function () { it('exports ODT', async function () {
this.timeout(3000);
await agent.get(`/p/${testPadId}/export/odt`) await agent.get(`/p/${testPadId}/export/odt`)
.buffer(true).parse(superagent.parse['application/octet-stream']) .buffer(true).parse(superagent.parse['application/octet-stream'])
.expect(200) .expect(200)
@ -193,6 +206,7 @@ describe(__filename, function () {
}); // End of AbiWord/LibreOffice tests. }); // End of AbiWord/LibreOffice tests.
it('Tries to import .etherpad', async function () { it('Tries to import .etherpad', async function () {
this.timeout(3000);
await agent.post(`/p/${testPadId}/import`) await agent.post(`/p/${testPadId}/import`)
.attach('file', etherpadDoc, { .attach('file', etherpadDoc, {
filename: '/test.etherpad', filename: '/test.etherpad',
@ -203,6 +217,7 @@ describe(__filename, function () {
}); });
it('exports Etherpad', async function () { it('exports Etherpad', async function () {
this.timeout(3000);
await agent.get(`/p/${testPadId}/export/etherpad`) await agent.get(`/p/${testPadId}/export/etherpad`)
.buffer(true).parse(superagent.parse.text) .buffer(true).parse(superagent.parse.text)
.expect(200) .expect(200)
@ -210,6 +225,7 @@ describe(__filename, function () {
}); });
it('exports HTML for this Etherpad file', async function () { it('exports HTML for this Etherpad file', async function () {
this.timeout(3000);
await agent.get(`/p/${testPadId}/export/html`) await agent.get(`/p/${testPadId}/export/html`)
.expect(200) .expect(200)
.expect('content-type', 'text/html; charset=utf-8') .expect('content-type', 'text/html; charset=utf-8')
@ -217,6 +233,7 @@ describe(__filename, function () {
}); });
it('Tries to import unsupported file type', async function () { it('Tries to import unsupported file type', async function () {
this.timeout(3000);
settings.allowUnknownFileEnds = false; settings.allowUnknownFileEnds = false;
await agent.post(`/p/${testPadId}/import`) await agent.post(`/p/${testPadId}/import`)
.attach('file', padText, {filename: '/test.xasdasdxx', contentType: 'weirdness/jobby'}) .attach('file', padText, {filename: '/test.xasdasdxx', contentType: 'weirdness/jobby'})
@ -252,6 +269,7 @@ describe(__filename, function () {
}); });
it('!authn !exist -> create', async function () { it('!authn !exist -> create', async function () {
this.timeout(100);
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
.attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'})
.expect(200); .expect(200);
@ -261,6 +279,7 @@ describe(__filename, function () {
}); });
it('!authn exist -> replace', async function () { it('!authn exist -> replace', async function () {
this.timeout(100);
const pad = await createTestPad('before import'); const pad = await createTestPad('before import');
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
.attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'})
@ -270,6 +289,7 @@ describe(__filename, function () {
}); });
it('authn anonymous !exist -> fail', async function () { it('authn anonymous !exist -> fail', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
.attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'})
@ -278,6 +298,7 @@ describe(__filename, function () {
}); });
it('authn anonymous exist -> fail', async function () { it('authn anonymous exist -> fail', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
const pad = await createTestPad('before import\n'); const pad = await createTestPad('before import\n');
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
@ -287,6 +308,7 @@ describe(__filename, function () {
}); });
it('authn user create !exist -> create', async function () { it('authn user create !exist -> create', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
.auth('user', 'user-password') .auth('user', 'user-password')
@ -298,6 +320,7 @@ describe(__filename, function () {
}); });
it('authn user modify !exist -> fail', async function () { it('authn user modify !exist -> fail', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
authorize = () => 'modify'; authorize = () => 'modify';
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
@ -308,6 +331,7 @@ describe(__filename, function () {
}); });
it('authn user readonly !exist -> fail', async function () { it('authn user readonly !exist -> fail', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
authorize = () => 'readOnly'; authorize = () => 'readOnly';
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
@ -318,6 +342,7 @@ describe(__filename, function () {
}); });
it('authn user create exist -> replace', async function () { it('authn user create exist -> replace', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
const pad = await createTestPad('before import\n'); const pad = await createTestPad('before import\n');
await agent.post(`/p/${testPadIdEnc}/import`) await agent.post(`/p/${testPadIdEnc}/import`)
@ -328,6 +353,7 @@ describe(__filename, function () {
}); });
it('authn user modify exist -> replace', async function () { it('authn user modify exist -> replace', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
authorize = () => 'modify'; authorize = () => 'modify';
const pad = await createTestPad('before import\n'); const pad = await createTestPad('before import\n');
@ -339,6 +365,7 @@ describe(__filename, function () {
}); });
it('authn user readonly exist -> fail', async function () { it('authn user readonly exist -> fail', async function () {
this.timeout(100);
const pad = await createTestPad('before import\n'); const pad = await createTestPad('before import\n');
settings.requireAuthentication = true; settings.requireAuthentication = true;
authorize = () => 'readOnly'; authorize = () => 'readOnly';

View file

@ -15,6 +15,7 @@ const apiVersion = '1.2.14';
describe(__filename, function () { describe(__filename, function () {
describe('Connectivity for instance-level API tests', function () { describe('Connectivity for instance-level API tests', function () {
it('can connect', function (done) { it('can connect', function (done) {
this.timeout(150);
api.get('/api/') api.get('/api/')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200, done); .expect(200, done);
@ -23,6 +24,7 @@ describe(__filename, function () {
describe('getStats', function () { describe('getStats', function () {
it('Gets the stats of a running instance', function (done) { it('Gets the stats of a running instance', function (done) {
this.timeout(100);
api.get(endPoint('getStats')) api.get(endPoint('getStats'))
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('getStats() failed'); if (res.body.code !== 0) throw new Error('getStats() failed');

View file

@ -47,6 +47,7 @@ const expectedSpaceHtml = '<!doctype html><html><body><ul class="bullet"><li>one
describe(__filename, function () { describe(__filename, function () {
describe('Connectivity', function () { describe('Connectivity', function () {
it('can connect', function (done) { it('can connect', function (done) {
this.timeout(200);
api.get('/api/') api.get('/api/')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200, done); .expect(200, done);
@ -55,6 +56,7 @@ describe(__filename, function () {
describe('API Versioning', function () { describe('API Versioning', function () {
it('finds the version tag', function (done) { it('finds the version tag', function (done) {
this.timeout(150);
api.get('/api/') api.get('/api/')
.expect((res) => { .expect((res) => {
apiVersion = res.body.currentVersion; apiVersion = res.body.currentVersion;
@ -67,6 +69,7 @@ describe(__filename, function () {
describe('Permission', function () { describe('Permission', function () {
it('errors with invalid APIKey', function (done) { it('errors with invalid APIKey', function (done) {
this.timeout(150);
// This is broken because Etherpad doesn't handle HTTP codes properly see #2343 // 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 // If your APIKey is password you deserve to fail all tests anyway
const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`; const permErrorURL = `/api/${apiVersion}/createPad?apikey=password&padID=test`;
@ -119,6 +122,7 @@ describe(__filename, function () {
describe('deletePad', function () { describe('deletePad', function () {
it('deletes a Pad', function (done) { it('deletes a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('deletePad')}&padID=${testPadId}`) api.get(`${endPoint('deletePad')}&padID=${testPadId}`)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200, done); // @TODO: we shouldn't expect 200 here since the pad may not exist .expect(200, done); // @TODO: we shouldn't expect 200 here since the pad may not exist
@ -127,6 +131,7 @@ describe(__filename, function () {
describe('createPad', function () { describe('createPad', function () {
it('creates a new Pad', function (done) { it('creates a new Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('createPad')}&padID=${testPadId}`) api.get(`${endPoint('createPad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to create new Pad'); if (res.body.code !== 0) throw new Error('Unable to create new Pad');
@ -138,6 +143,7 @@ describe(__filename, function () {
describe('getRevisionsCount', function () { describe('getRevisionsCount', function () {
it('gets revision count of Pad', function (done) { it('gets revision count of Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`) api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to get Revision Count'); if (res.body.code !== 0) throw new Error('Unable to get Revision Count');
@ -150,6 +156,7 @@ describe(__filename, function () {
describe('getSavedRevisionsCount', function () { describe('getSavedRevisionsCount', function () {
it('gets saved revisions count of Pad', function (done) { it('gets saved revisions count of Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`) api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count'); if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count');
@ -162,6 +169,7 @@ describe(__filename, function () {
describe('listSavedRevisions', function () { describe('listSavedRevisions', function () {
it('gets saved revision list of Pad', function (done) { it('gets saved revision list of Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`) api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List'); if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List');
@ -174,6 +182,7 @@ describe(__filename, function () {
describe('getHTML', function () { describe('getHTML', function () {
it('get the HTML of Pad', function (done) { it('get the HTML of Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('getHTML')}&padID=${testPadId}`) api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.html.length <= 1) throw new Error('Unable to get the HTML'); if (res.body.data.html.length <= 1) throw new Error('Unable to get the HTML');
@ -185,6 +194,7 @@ describe(__filename, function () {
describe('listAllPads', function () { describe('listAllPads', function () {
it('list all pads', function (done) { it('list all pads', function (done) {
this.timeout(150);
api.get(endPoint('listAllPads')) api.get(endPoint('listAllPads'))
.expect((res) => { .expect((res) => {
if (res.body.data.padIDs.includes(testPadId) !== true) { if (res.body.data.padIDs.includes(testPadId) !== true) {
@ -198,6 +208,7 @@ describe(__filename, function () {
describe('deletePad', function () { describe('deletePad', function () {
it('deletes a Pad', function (done) { it('deletes a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('deletePad')}&padID=${testPadId}`) api.get(`${endPoint('deletePad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Deletion failed'); if (res.body.code !== 0) throw new Error('Pad Deletion failed');
@ -209,6 +220,7 @@ describe(__filename, function () {
describe('listAllPads', function () { describe('listAllPads', function () {
it('list all pads', function (done) { it('list all pads', function (done) {
this.timeout(150);
api.get(endPoint('listAllPads')) api.get(endPoint('listAllPads'))
.expect((res) => { .expect((res) => {
if (res.body.data.padIDs.includes(testPadId) !== false) { if (res.body.data.padIDs.includes(testPadId) !== false) {
@ -222,6 +234,7 @@ describe(__filename, function () {
describe('getHTML', function () { describe('getHTML', function () {
it('get the HTML of a Pad -- Should return a failure', function (done) { it('get the HTML of a Pad -- Should return a failure', function (done) {
this.timeout(150);
api.get(`${endPoint('getHTML')}&padID=${testPadId}`) api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 1) throw new Error('Pad deletion failed'); if (res.body.code !== 1) throw new Error('Pad deletion failed');
@ -233,6 +246,7 @@ describe(__filename, function () {
describe('createPad', function () { describe('createPad', function () {
it('creates a new Pad with text', function (done) { it('creates a new Pad with text', function (done) {
this.timeout(200);
api.get(`${endPoint('createPad')}&padID=${testPadId}&text=testText`) api.get(`${endPoint('createPad')}&padID=${testPadId}&text=testText`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Creation failed'); if (res.body.code !== 0) throw new Error('Pad Creation failed');
@ -244,6 +258,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it('gets the Pad text and expect it to be testText with \n which is a line break', function (done) { it('gets the Pad text and expect it to be testText with \n which is a line break', function (done) {
this.timeout(150);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.text !== 'testText\n') throw new Error('Pad Creation with text'); if (res.body.data.text !== 'testText\n') throw new Error('Pad Creation with text');
@ -255,6 +270,7 @@ describe(__filename, function () {
describe('setText', function () { describe('setText', function () {
it('creates a new Pad with text', function (done) { it('creates a new Pad with text', function (done) {
this.timeout(200);
api.post(endPoint('setText')) api.post(endPoint('setText'))
.send({ .send({
padID: testPadId, padID: testPadId,
@ -270,6 +286,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it('gets the Pad text', function (done) { it('gets the Pad text', function (done) {
this.timeout(150);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.text !== 'testTextTwo\n') throw new Error('Setting Text'); if (res.body.data.text !== 'testTextTwo\n') throw new Error('Setting Text');
@ -281,6 +298,7 @@ describe(__filename, function () {
describe('getRevisionsCount', function () { describe('getRevisionsCount', function () {
it('gets Revision Count of a Pad', function (done) { it('gets Revision Count of a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`) api.get(`${endPoint('getRevisionsCount')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.revisions !== 1) throw new Error('Unable to get text revision count'); if (res.body.data.revisions !== 1) throw new Error('Unable to get text revision count');
@ -292,6 +310,7 @@ describe(__filename, function () {
describe('saveRevision', function () { describe('saveRevision', function () {
it('saves Revision', function (done) { it('saves Revision', function (done) {
this.timeout(150);
api.get(`${endPoint('saveRevision')}&padID=${testPadId}`) api.get(`${endPoint('saveRevision')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to save Revision'); if (res.body.code !== 0) throw new Error('Unable to save Revision');
@ -303,6 +322,7 @@ describe(__filename, function () {
describe('getSavedRevisionsCount', function () { describe('getSavedRevisionsCount', function () {
it('gets saved revisions count of Pad', function (done) { it('gets saved revisions count of Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`) api.get(`${endPoint('getSavedRevisionsCount')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count'); if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions Count');
@ -315,6 +335,7 @@ describe(__filename, function () {
describe('listSavedRevisions', function () { describe('listSavedRevisions', function () {
it('gets saved revision list of Pad', function (done) { it('gets saved revision list of Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`) api.get(`${endPoint('listSavedRevisions')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List'); if (res.body.code !== 0) throw new Error('Unable to get Saved Revisions List');
@ -326,6 +347,7 @@ describe(__filename, function () {
}); });
describe('padUsersCount', function () { describe('padUsersCount', function () {
it('gets User Count of a Pad', function (done) { it('gets User Count of a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('padUsersCount')}&padID=${testPadId}`) api.get(`${endPoint('padUsersCount')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.padUsersCount !== 0) throw new Error('Incorrect Pad User count'); if (res.body.data.padUsersCount !== 0) throw new Error('Incorrect Pad User count');
@ -337,6 +359,7 @@ describe(__filename, function () {
describe('getReadOnlyID', function () { describe('getReadOnlyID', function () {
it('Gets the Read Only ID of a Pad', function (done) { it('Gets the Read Only ID of a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`) api.get(`${endPoint('getReadOnlyID')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (!res.body.data.readOnlyID) throw new Error('No Read Only ID for Pad'); if (!res.body.data.readOnlyID) throw new Error('No Read Only ID for Pad');
@ -348,6 +371,7 @@ describe(__filename, function () {
describe('listAuthorsOfPad', function () { describe('listAuthorsOfPad', function () {
it('Get Authors of the Pad', function (done) { it('Get Authors of the Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('listAuthorsOfPad')}&padID=${testPadId}`) api.get(`${endPoint('listAuthorsOfPad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.authorIDs.length !== 0) throw new Error('# of Authors of pad is not 0'); if (res.body.data.authorIDs.length !== 0) throw new Error('# of Authors of pad is not 0');
@ -359,6 +383,7 @@ describe(__filename, function () {
describe('getLastEdited', function () { describe('getLastEdited', function () {
it('Get When Pad was left Edited', function (done) { it('Get When Pad was left Edited', function (done) {
this.timeout(150);
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (!res.body.data.lastEdited) { if (!res.body.data.lastEdited) {
@ -374,6 +399,7 @@ describe(__filename, function () {
describe('setText', function () { describe('setText', function () {
it('creates a new Pad with text', function (done) { it('creates a new Pad with text', function (done) {
this.timeout(200);
api.post(endPoint('setText')) api.post(endPoint('setText'))
.send({ .send({
padID: testPadId, padID: testPadId,
@ -389,6 +415,7 @@ describe(__filename, function () {
describe('getLastEdited', function () { describe('getLastEdited', function () {
it('Get When Pad was left Edited', function (done) { it('Get When Pad was left Edited', function (done) {
this.timeout(150);
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.lastEdited <= lastEdited) { if (res.body.data.lastEdited <= lastEdited) {
@ -402,6 +429,7 @@ describe(__filename, function () {
describe('padUsers', function () { describe('padUsers', function () {
it('gets User Count of a Pad', function (done) { it('gets User Count of a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('padUsers')}&padID=${testPadId}`) api.get(`${endPoint('padUsers')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.padUsers.length !== 0) throw new Error('Incorrect Pad Users'); if (res.body.data.padUsers.length !== 0) throw new Error('Incorrect Pad Users');
@ -413,6 +441,7 @@ describe(__filename, function () {
describe('deletePad', function () { describe('deletePad', function () {
it('deletes a Pad', function (done) { it('deletes a Pad', function (done) {
this.timeout(150);
api.get(`${endPoint('deletePad')}&padID=${testPadId}`) api.get(`${endPoint('deletePad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Deletion failed'); if (res.body.code !== 0) throw new Error('Pad Deletion failed');
@ -428,6 +457,7 @@ describe(__filename, function () {
describe('createPad', function () { describe('createPad', function () {
it('creates a new Pad with text', function (done) { it('creates a new Pad with text', function (done) {
this.timeout(200);
api.get(`${endPoint('createPad')}&padID=${testPadId}`) api.get(`${endPoint('createPad')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Creation failed'); if (res.body.code !== 0) throw new Error('Pad Creation failed');
@ -439,6 +469,7 @@ describe(__filename, function () {
describe('setText', function () { describe('setText', function () {
it('Sets text on a pad Id', function (done) { it('Sets text on a pad Id', function (done) {
this.timeout(150);
api.post(`${endPoint('setText')}&padID=${testPadId}`) api.post(`${endPoint('setText')}&padID=${testPadId}`)
.field({text}) .field({text})
.expect((res) => { .expect((res) => {
@ -451,6 +482,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it('Gets text on a pad Id', function (done) { it('Gets text on a pad Id', function (done) {
this.timeout(200);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Get Text failed'); if (res.body.code !== 0) throw new Error('Pad Get Text failed');
@ -463,6 +495,7 @@ describe(__filename, function () {
describe('setText', function () { describe('setText', function () {
it('Sets text on a pad Id including an explicit newline', function (done) { it('Sets text on a pad Id including an explicit newline', function (done) {
this.timeout(200);
api.post(`${endPoint('setText')}&padID=${testPadId}`) api.post(`${endPoint('setText')}&padID=${testPadId}`)
.field({text: `${text}\n`}) .field({text: `${text}\n`})
.expect((res) => { .expect((res) => {
@ -475,6 +508,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it("Gets text on a pad Id and doesn't have an excess newline", function (done) { it("Gets text on a pad Id and doesn't have an excess newline", function (done) {
this.timeout(150);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Get Text failed'); if (res.body.code !== 0) throw new Error('Pad Get Text failed');
@ -487,6 +521,7 @@ describe(__filename, function () {
describe('getLastEdited', function () { describe('getLastEdited', function () {
it('Gets when pad was last edited', function (done) { it('Gets when pad was last edited', function (done) {
this.timeout(150);
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed'); if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed');
@ -498,6 +533,7 @@ describe(__filename, function () {
describe('movePad', function () { describe('movePad', function () {
it('Move a Pad to a different Pad ID', function (done) { it('Move a Pad to a different Pad ID', function (done) {
this.timeout(200);
api.get(`${endPoint('movePad')}&sourceID=${testPadId}&destinationID=${newPadId}&force=true`) api.get(`${endPoint('movePad')}&sourceID=${testPadId}&destinationID=${newPadId}&force=true`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Moving Pad Failed'); if (res.body.code !== 0) throw new Error('Moving Pad Failed');
@ -509,6 +545,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it('Gets text on a pad Id', function (done) { it('Gets text on a pad Id', function (done) {
this.timeout(150);
api.get(`${endPoint('getText')}&padID=${newPadId}`) api.get(`${endPoint('getText')}&padID=${newPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed'); if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed');
@ -520,6 +557,7 @@ describe(__filename, function () {
describe('movePad', function () { describe('movePad', function () {
it('Move a Pad to a different Pad ID', function (done) { it('Move a Pad to a different Pad ID', function (done) {
this.timeout(200);
api.get(`${endPoint('movePad')}&sourceID=${newPadId}&destinationID=${testPadId}&force=false`) api.get(`${endPoint('movePad')}&sourceID=${newPadId}&destinationID=${testPadId}&force=false`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Moving Pad Failed'); if (res.body.code !== 0) throw new Error('Moving Pad Failed');
@ -531,6 +569,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it('Gets text on a pad Id', function (done) { it('Gets text on a pad Id', function (done) {
this.timeout(150);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed'); if (res.body.data.text !== `${text}\n`) throw new Error('Pad Get Text failed');
@ -542,6 +581,7 @@ describe(__filename, function () {
describe('getLastEdited', function () { describe('getLastEdited', function () {
it('Gets when pad was last edited', function (done) { it('Gets when pad was last edited', function (done) {
this.timeout(150);
api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`) api.get(`${endPoint('getLastEdited')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed'); if (res.body.lastEdited === 0) throw new Error('Get Last Edited Failed');
@ -553,6 +593,7 @@ describe(__filename, function () {
describe('appendText', function () { describe('appendText', function () {
it('Append text to a pad Id', function (done) { it('Append text to a pad Id', function (done) {
this.timeout(150);
api.get(`${endPoint('appendText', '1.2.13')}&padID=${testPadId}&text=hello`) api.get(`${endPoint('appendText', '1.2.13')}&padID=${testPadId}&text=hello`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Append Text failed'); if (res.body.code !== 0) throw new Error('Pad Append Text failed');
@ -564,6 +605,7 @@ describe(__filename, function () {
describe('getText', function () { describe('getText', function () {
it('Gets text on a pad Id', function (done) { it('Gets text on a pad Id', function (done) {
this.timeout(150);
api.get(`${endPoint('getText')}&padID=${testPadId}`) api.get(`${endPoint('getText')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Pad Get Text failed'); if (res.body.code !== 0) throw new Error('Pad Get Text failed');
@ -577,6 +619,7 @@ describe(__filename, function () {
describe('setHTML', function () { describe('setHTML', function () {
it('Sets the HTML of a Pad attempting to pass ugly HTML', function (done) { it('Sets the HTML of a Pad attempting to pass ugly HTML', function (done) {
this.timeout(200);
const html = '<div><b>Hello HTML</title></head></div>'; const html = '<div><b>Hello HTML</title></head></div>';
api.post(endPoint('setHTML')) api.post(endPoint('setHTML'))
.send({ .send({
@ -593,6 +636,7 @@ describe(__filename, function () {
describe('setHTML', function () { describe('setHTML', function () {
it('Sets the HTML of a Pad with complex nested lists of different types', function (done) { it('Sets the HTML of a Pad with complex nested lists of different types', function (done) {
this.timeout(200);
api.post(endPoint('setHTML')) api.post(endPoint('setHTML'))
.send({ .send({
padID: testPadId, padID: testPadId,
@ -608,6 +652,7 @@ describe(__filename, function () {
describe('getHTML', function () { describe('getHTML', function () {
it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) { it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) {
this.timeout(150);
api.get(`${endPoint('getHTML')}&padID=${testPadId}`) api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
const receivedHtml = res.body.data.html.replace('<br></body>', '</body>').toLowerCase(); const receivedHtml = res.body.data.html.replace('<br></body>', '</body>').toLowerCase();
@ -631,6 +676,7 @@ describe(__filename, function () {
describe('setHTML', function () { describe('setHTML', function () {
it('Sets the HTML of a Pad with white space between list items', function (done) { it('Sets the HTML of a Pad with white space between list items', function (done) {
this.timeout(200);
api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${ulSpaceHtml}`) api.get(`${endPoint('setHTML')}&padID=${testPadId}&html=${ulSpaceHtml}`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('List HTML cant be imported'); if (res.body.code !== 0) throw new Error('List HTML cant be imported');
@ -642,6 +688,7 @@ describe(__filename, function () {
describe('getHTML', function () { describe('getHTML', function () {
it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) { it('Gets back the HTML of a Pad with complex nested lists of different types', function (done) {
this.timeout(150);
api.get(`${endPoint('getHTML')}&padID=${testPadId}`) api.get(`${endPoint('getHTML')}&padID=${testPadId}`)
.expect((res) => { .expect((res) => {
const receivedHtml = res.body.data.html.replace('<br></body>', '</body>').toLowerCase(); const receivedHtml = res.body.data.html.replace('<br></body>', '</body>').toLowerCase();
@ -664,6 +711,7 @@ describe(__filename, function () {
describe('createPad', function () { describe('createPad', function () {
it('errors if pad can be created', function (done) { it('errors if pad can be created', function (done) {
this.timeout(150);
const badUrlChars = ['/', '%23', '%3F', '%26']; const badUrlChars = ['/', '%23', '%3F', '%26'];
async.map( async.map(
badUrlChars, badUrlChars,
@ -681,6 +729,7 @@ describe(__filename, function () {
describe('copyPad', function () { describe('copyPad', function () {
it('copies the content of a existent pad', function (done) { it('copies the content of a existent pad', function (done) {
this.timeout(200);
api.get(`${endPoint('copyPad')}&sourceID=${testPadId}&destinationID=${copiedPadId}&force=true`) api.get(`${endPoint('copyPad')}&sourceID=${testPadId}&destinationID=${copiedPadId}&force=true`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Copy Pad Failed'); if (res.body.code !== 0) throw new Error('Copy Pad Failed');
@ -703,6 +752,7 @@ describe(__filename, function () {
}); });
it('returns a successful response', function (done) { it('returns a successful response', function (done) {
this.timeout(200);
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`) api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed'); if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed');
@ -713,6 +763,7 @@ describe(__filename, function () {
// this test validates if the source pad's text and attributes are kept // 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) { 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`) api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${newPad}&force=false`)
.expect((res) => { .expect((res) => {
if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed'); if (res.body.code !== 0) throw new Error('Copy Pad Without History Failed');
@ -742,6 +793,7 @@ describe(__filename, function () {
const padId = makeid(); const padId = makeid();
const padWithNonExistentGroup = `notExistentGroup$${padId}`; const padWithNonExistentGroup = `notExistentGroup$${padId}`;
it('throws an error', function (done) { it('throws an error', function (done) {
this.timeout(150);
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padWithNonExistentGroup}&force=true`) api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padWithNonExistentGroup}&force=true`)
.expect((res) => { .expect((res) => {
// code 1, it means an error has happened // code 1, it means an error has happened
@ -760,6 +812,7 @@ describe(__filename, function () {
context('and force is false', function () { context('and force is false', function () {
it('throws an error', function (done) { it('throws an error', function (done) {
this.timeout(150);
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=false`) api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=false`)
.expect((res) => { .expect((res) => {
// code 1, it means an error has happened // code 1, it means an error has happened
@ -771,6 +824,7 @@ describe(__filename, function () {
context('and force is true', function () { context('and force is true', function () {
it('returns a successful response', function (done) { it('returns a successful response', function (done) {
this.timeout(200);
api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=true`) api.get(`${endPoint('copyPadWithoutHistory')}&sourceID=${sourcePadId}&destinationID=${padIdExistent}&force=true`)
.expect((res) => { .expect((res) => {
// code 1, it means an error has happened // code 1, it means an error has happened

View file

@ -15,6 +15,7 @@ let padID = makeid();
describe(__filename, function () { describe(__filename, function () {
describe('API Versioning', function () { describe('API Versioning', function () {
it('errors if can not connect', async function () { it('errors if can not connect', async function () {
this.timeout(200);
await api.get('/api/') await api.get('/api/')
.expect(200) .expect(200)
.expect((res) => { .expect((res) => {
@ -56,6 +57,7 @@ describe(__filename, function () {
describe('API: Group creation and deletion', function () { describe('API: Group creation and deletion', function () {
it('createGroup', async function () { it('createGroup', async function () {
this.timeout(100);
await api.get(endPoint('createGroup')) await api.get(endPoint('createGroup'))
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -67,6 +69,7 @@ describe(__filename, function () {
}); });
it('listSessionsOfGroup for empty group', async function () { it('listSessionsOfGroup for empty group', async function () {
this.timeout(100);
await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`) await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -77,6 +80,7 @@ describe(__filename, function () {
}); });
it('deleteGroup', async function () { it('deleteGroup', async function () {
this.timeout(100);
await api.get(`${endPoint('deleteGroup')}&groupID=${groupID}`) await api.get(`${endPoint('deleteGroup')}&groupID=${groupID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -86,6 +90,7 @@ describe(__filename, function () {
}); });
it('createGroupIfNotExistsFor', async function () { it('createGroupIfNotExistsFor', async function () {
this.timeout(100);
await api.get(`${endPoint('createGroupIfNotExistsFor')}&groupMapper=management`) await api.get(`${endPoint('createGroupIfNotExistsFor')}&groupMapper=management`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -98,6 +103,7 @@ describe(__filename, function () {
// Test coverage for https://github.com/ether/etherpad-lite/issues/4227 // Test coverage for https://github.com/ether/etherpad-lite/issues/4227
// Creates a group, creates 2 sessions, 2 pads and then deletes the group. // Creates a group, creates 2 sessions, 2 pads and then deletes the group.
it('createGroup', async function () { it('createGroup', async function () {
this.timeout(100);
await api.get(endPoint('createGroup')) await api.get(endPoint('createGroup'))
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -109,6 +115,7 @@ describe(__filename, function () {
}); });
it('createAuthor', async function () { it('createAuthor', async function () {
this.timeout(100);
await api.get(endPoint('createAuthor')) await api.get(endPoint('createAuthor'))
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -120,6 +127,7 @@ describe(__filename, function () {
}); });
it('createSession', async function () { it('createSession', async function () {
this.timeout(100);
await api.get(`${endPoint('createSession') await api.get(`${endPoint('createSession')
}&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`) }&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`)
.expect(200) .expect(200)
@ -132,6 +140,7 @@ describe(__filename, function () {
}); });
it('createSession', async function () { it('createSession', async function () {
this.timeout(100);
await api.get(`${endPoint('createSession') await api.get(`${endPoint('createSession')
}&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`) }&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`)
.expect(200) .expect(200)
@ -144,6 +153,7 @@ describe(__filename, function () {
}); });
it('createGroupPad', async function () { it('createGroupPad', async function () {
this.timeout(100);
await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=x1234567`) await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=x1234567`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -153,6 +163,7 @@ describe(__filename, function () {
}); });
it('createGroupPad', async function () { it('createGroupPad', async function () {
this.timeout(100);
await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=x12345678`) await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=x12345678`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -162,6 +173,7 @@ describe(__filename, function () {
}); });
it('deleteGroup', async function () { it('deleteGroup', async function () {
this.timeout(100);
await api.get(`${endPoint('deleteGroup')}&groupID=${groupID}`) await api.get(`${endPoint('deleteGroup')}&groupID=${groupID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -174,6 +186,7 @@ describe(__filename, function () {
describe('API: Author creation', function () { describe('API: Author creation', function () {
it('createGroup', async function () { it('createGroup', async function () {
this.timeout(100);
await api.get(endPoint('createGroup')) await api.get(endPoint('createGroup'))
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -185,6 +198,7 @@ describe(__filename, function () {
}); });
it('createAuthor', async function () { it('createAuthor', async function () {
this.timeout(100);
await api.get(endPoint('createAuthor')) await api.get(endPoint('createAuthor'))
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -195,6 +209,7 @@ describe(__filename, function () {
}); });
it('createAuthor with name', async function () { it('createAuthor with name', async function () {
this.timeout(100);
await api.get(`${endPoint('createAuthor')}&name=john`) await api.get(`${endPoint('createAuthor')}&name=john`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -206,6 +221,7 @@ describe(__filename, function () {
}); });
it('createAuthorIfNotExistsFor', async function () { it('createAuthorIfNotExistsFor', async function () {
this.timeout(100);
await api.get(`${endPoint('createAuthorIfNotExistsFor')}&authorMapper=chris`) await api.get(`${endPoint('createAuthorIfNotExistsFor')}&authorMapper=chris`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -216,6 +232,7 @@ describe(__filename, function () {
}); });
it('getAuthorName', async function () { it('getAuthorName', async function () {
this.timeout(100);
await api.get(`${endPoint('getAuthorName')}&authorID=${authorID}`) await api.get(`${endPoint('getAuthorName')}&authorID=${authorID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -228,6 +245,7 @@ describe(__filename, function () {
describe('API: Sessions', function () { describe('API: Sessions', function () {
it('createSession', async function () { it('createSession', async function () {
this.timeout(100);
await api.get(`${endPoint('createSession') await api.get(`${endPoint('createSession')
}&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`) }&authorID=${authorID}&groupID=${groupID}&validUntil=999999999999`)
.expect(200) .expect(200)
@ -240,6 +258,7 @@ describe(__filename, function () {
}); });
it('getSessionInfo', async function () { it('getSessionInfo', async function () {
this.timeout(100);
await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`) await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -252,6 +271,7 @@ describe(__filename, function () {
}); });
it('listSessionsOfGroup', async function () { it('listSessionsOfGroup', async function () {
this.timeout(100);
await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`) await api.get(`${endPoint('listSessionsOfGroup')}&groupID=${groupID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -262,6 +282,7 @@ describe(__filename, function () {
}); });
it('deleteSession', async function () { it('deleteSession', async function () {
this.timeout(100);
await api.get(`${endPoint('deleteSession')}&sessionID=${sessionID}`) await api.get(`${endPoint('deleteSession')}&sessionID=${sessionID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -271,6 +292,7 @@ describe(__filename, function () {
}); });
it('getSessionInfo of deleted session', async function () { it('getSessionInfo of deleted session', async function () {
this.timeout(100);
await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`) await api.get(`${endPoint('getSessionInfo')}&sessionID=${sessionID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -282,6 +304,7 @@ describe(__filename, function () {
describe('API: Group pad management', function () { describe('API: Group pad management', function () {
it('listPads', async function () { it('listPads', async function () {
this.timeout(100);
await api.get(`${endPoint('listPads')}&groupID=${groupID}`) await api.get(`${endPoint('listPads')}&groupID=${groupID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -292,6 +315,7 @@ describe(__filename, function () {
}); });
it('createGroupPad', async function () { it('createGroupPad', async function () {
this.timeout(100);
await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=${padID}`) await api.get(`${endPoint('createGroupPad')}&groupID=${groupID}&padName=${padID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -302,6 +326,7 @@ describe(__filename, function () {
}); });
it('listPads after creating a group pad', async function () { it('listPads after creating a group pad', async function () {
this.timeout(100);
await api.get(`${endPoint('listPads')}&groupID=${groupID}`) await api.get(`${endPoint('listPads')}&groupID=${groupID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -314,6 +339,7 @@ describe(__filename, function () {
describe('API: Pad security', function () { describe('API: Pad security', function () {
it('getPublicStatus', async function () { it('getPublicStatus', async function () {
this.timeout(100);
await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`) await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -324,6 +350,7 @@ describe(__filename, function () {
}); });
it('setPublicStatus', async function () { it('setPublicStatus', async function () {
this.timeout(100);
await api.get(`${endPoint('setPublicStatus')}&padID=${padID}&publicStatus=true`) await api.get(`${endPoint('setPublicStatus')}&padID=${padID}&publicStatus=true`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -333,6 +360,7 @@ describe(__filename, function () {
}); });
it('getPublicStatus after changing public status', async function () { it('getPublicStatus after changing public status', async function () {
this.timeout(100);
await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`) await api.get(`${endPoint('getPublicStatus')}&padID=${padID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -349,6 +377,7 @@ describe(__filename, function () {
describe('API: Misc', function () { describe('API: Misc', function () {
it('listPadsOfAuthor', async function () { it('listPadsOfAuthor', async function () {
this.timeout(100);
await api.get(`${endPoint('listPadsOfAuthor')}&authorID=${authorID}`) await api.get(`${endPoint('listPadsOfAuthor')}&authorID=${authorID}`)
.expect(200) .expect(200)
.expect('Content-Type', /json/) .expect('Content-Type', /json/)

View file

@ -285,6 +285,7 @@ describe(__filename, function () {
} }
it(testObj.description, async function () { it(testObj.description, async function () {
this.timeout(250);
const $ = cheerio.load(testObj.html); // Load HTML into Cheerio const $ = cheerio.load(testObj.html); // Load HTML into Cheerio
const doc = $('body')[0]; // Creates a dom-like representation of HTML const doc = $('body')[0]; // Creates a dom-like representation of HTML
// Create an empty attribute pool // Create an empty attribute pool

View file

@ -93,11 +93,13 @@ describe(__filename, function () {
describe('basic behavior', function () { describe('basic behavior', function () {
it('passes hook name', async function () { it('passes hook name', async function () {
this.timeout(30);
hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
callHookFnSync(hook); callHookFnSync(hook);
}); });
it('passes context', async function () { it('passes context', async function () {
this.timeout(30);
for (const val of ['value', null, undefined]) { for (const val of ['value', null, undefined]) {
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); }; hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); };
callHookFnSync(hook, val); callHookFnSync(hook, val);
@ -105,6 +107,7 @@ describe(__filename, function () {
}); });
it('returns the value provided to the callback', async function () { it('returns the value provided to the callback', async function () {
this.timeout(30);
for (const val of ['value', null, undefined]) { for (const val of ['value', null, undefined]) {
hook.hook_fn = (hn, ctx, cb) => { cb(ctx); }; hook.hook_fn = (hn, ctx, cb) => { cb(ctx); };
assert.equal(callHookFnSync(hook, val), val); assert.equal(callHookFnSync(hook, val), val);
@ -112,6 +115,7 @@ describe(__filename, function () {
}); });
it('returns the value returned by the hook function', async function () { it('returns the value returned by the hook function', async function () {
this.timeout(30);
for (const val of ['value', null, undefined]) { for (const val of ['value', null, undefined]) {
// Must not have the cb parameter otherwise returning undefined will error. // Must not have the cb parameter otherwise returning undefined will error.
hook.hook_fn = (hn, ctx) => ctx; hook.hook_fn = (hn, ctx) => ctx;
@ -120,16 +124,19 @@ describe(__filename, function () {
}); });
it('does not catch exceptions', async function () { it('does not catch exceptions', async function () {
this.timeout(30);
hook.hook_fn = () => { throw new Error('test exception'); }; hook.hook_fn = () => { throw new Error('test exception'); };
assert.throws(() => callHookFnSync(hook), {message: 'test exception'}); assert.throws(() => callHookFnSync(hook), {message: 'test exception'});
}); });
it('callback returns undefined', async function () { it('callback returns undefined', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); }; hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); };
callHookFnSync(hook); callHookFnSync(hook);
}); });
it('checks for deprecation', async function () { it('checks for deprecation', async function () {
this.timeout(30);
sinon.stub(console, 'warn'); sinon.stub(console, 'warn');
hooks.deprecationNotices[hookName] = 'test deprecation'; hooks.deprecationNotices[hookName] = 'test deprecation';
callHookFnSync(hook); callHookFnSync(hook);
@ -142,6 +149,7 @@ describe(__filename, function () {
describe('supported hook function styles', function () { describe('supported hook function styles', function () {
for (const tc of supportedSyncHookFunctions) { for (const tc of supportedSyncHookFunctions) {
it(tc.name, async function () { it(tc.name, async function () {
this.timeout(30);
sinon.stub(console, 'warn'); sinon.stub(console, 'warn');
sinon.stub(console, 'error'); sinon.stub(console, 'error');
hook.hook_fn = tc.fn; hook.hook_fn = tc.fn;
@ -186,6 +194,7 @@ describe(__filename, function () {
for (const tc of testCases) { for (const tc of testCases) {
it(tc.name, async function () { it(tc.name, async function () {
this.timeout(30);
sinon.stub(console, 'error'); sinon.stub(console, 'error');
hook.hook_fn = tc.fn; hook.hook_fn = tc.fn;
assert.equal(callHookFnSync(hook), tc.wantVal); assert.equal(callHookFnSync(hook), tc.wantVal);
@ -237,6 +246,7 @@ describe(__filename, function () {
if (step1.async && step2.async) continue; if (step1.async && step2.async) continue;
it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () { it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx, cb) => { hook.hook_fn = (hn, ctx, cb) => {
step1.fn(cb, new Error(ctx.ret1), ctx.ret1); step1.fn(cb, new Error(ctx.ret1), ctx.ret1);
return step2.fn(cb, new Error(ctx.ret2), ctx.ret2); return step2.fn(cb, new Error(ctx.ret2), ctx.ret2);
@ -300,6 +310,7 @@ describe(__filename, function () {
if (step1.rejects !== step2.rejects) continue; if (step1.rejects !== step2.rejects) continue;
it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () { it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () {
this.timeout(30);
const err = new Error('val'); const err = new Error('val');
hook.hook_fn = (hn, ctx, cb) => { hook.hook_fn = (hn, ctx, cb) => {
step1.fn(cb, err, 'val'); step1.fn(cb, err, 'val');
@ -325,27 +336,32 @@ describe(__filename, function () {
describe('hooks.callAll', function () { describe('hooks.callAll', function () {
describe('basic behavior', function () { describe('basic behavior', function () {
it('calls all in order', async function () { it('calls all in order', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(1), makeHook(2), makeHook(3)); testHooks.push(makeHook(1), makeHook(2), makeHook(3));
assert.deepEqual(hooks.callAll(hookName), [1, 2, 3]); assert.deepEqual(hooks.callAll(hookName), [1, 2, 3]);
}); });
it('passes hook name', async function () { it('passes hook name', async function () {
this.timeout(30);
hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
hooks.callAll(hookName); hooks.callAll(hookName);
}); });
it('undefined context -> {}', async function () { it('undefined context -> {}', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
hooks.callAll(hookName); hooks.callAll(hookName);
}); });
it('null context -> {}', async function () { it('null context -> {}', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
hooks.callAll(hookName, null); hooks.callAll(hookName, null);
}); });
it('context unmodified', async function () { it('context unmodified', async function () {
this.timeout(30);
const wantContext = {}; const wantContext = {};
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); }; hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); };
hooks.callAll(hookName, wantContext); hooks.callAll(hookName, wantContext);
@ -354,34 +370,40 @@ describe(__filename, function () {
describe('result processing', function () { describe('result processing', function () {
it('no registered hooks (undefined) -> []', async function () { it('no registered hooks (undefined) -> []', async function () {
this.timeout(30);
delete plugins.hooks.testHook; delete plugins.hooks.testHook;
assert.deepEqual(hooks.callAll(hookName), []); assert.deepEqual(hooks.callAll(hookName), []);
}); });
it('no registered hooks (empty list) -> []', async function () { it('no registered hooks (empty list) -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
assert.deepEqual(hooks.callAll(hookName), []); assert.deepEqual(hooks.callAll(hookName), []);
}); });
it('flattens one level', async function () { it('flattens one level', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]])); testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]]));
assert.deepEqual(hooks.callAll(hookName), [1, 2, [3]]); assert.deepEqual(hooks.callAll(hookName), [1, 2, [3]]);
}); });
it('filters out undefined', async function () { it('filters out undefined', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook([2]), makeHook([[3]])); testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]));
assert.deepEqual(hooks.callAll(hookName), [2, [3]]); assert.deepEqual(hooks.callAll(hookName), [2, [3]]);
}); });
it('preserves null', async function () { it('preserves null', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(null), makeHook([2]), makeHook([[3]])); testHooks.push(makeHook(null), makeHook([2]), makeHook([[3]]));
assert.deepEqual(hooks.callAll(hookName), [null, 2, [3]]); assert.deepEqual(hooks.callAll(hookName), [null, 2, [3]]);
}); });
it('all undefined -> []', async function () { it('all undefined -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook()); testHooks.push(makeHook(), makeHook());
assert.deepEqual(hooks.callAll(hookName), []); assert.deepEqual(hooks.callAll(hookName), []);
@ -391,37 +413,44 @@ describe(__filename, function () {
describe('hooks.callFirst', function () { describe('hooks.callFirst', function () {
it('no registered hooks (undefined) -> []', async function () { it('no registered hooks (undefined) -> []', async function () {
this.timeout(30);
delete plugins.hooks.testHook; delete plugins.hooks.testHook;
assert.deepEqual(hooks.callFirst(hookName), []); assert.deepEqual(hooks.callFirst(hookName), []);
}); });
it('no registered hooks (empty list) -> []', async function () { it('no registered hooks (empty list) -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
assert.deepEqual(hooks.callFirst(hookName), []); assert.deepEqual(hooks.callFirst(hookName), []);
}); });
it('passes hook name => {}', async function () { it('passes hook name => {}', async function () {
this.timeout(30);
hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
hooks.callFirst(hookName); hooks.callFirst(hookName);
}); });
it('undefined context => {}', async function () { it('undefined context => {}', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
hooks.callFirst(hookName); hooks.callFirst(hookName);
}); });
it('null context => {}', async function () { it('null context => {}', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
hooks.callFirst(hookName, null); hooks.callFirst(hookName, null);
}); });
it('context unmodified', async function () { it('context unmodified', async function () {
this.timeout(30);
const wantContext = {}; const wantContext = {};
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); }; hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); };
hooks.callFirst(hookName, wantContext); hooks.callFirst(hookName, wantContext);
}); });
it('predicate never satisfied -> calls all in order', async function () { it('predicate never satisfied -> calls all in order', async function () {
this.timeout(30);
const gotCalls = []; const gotCalls = [];
testHooks.length = 0; testHooks.length = 0;
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
@ -434,30 +463,35 @@ describe(__filename, function () {
}); });
it('stops when predicate is satisfied', async function () { it('stops when predicate is satisfied', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook('val1'), makeHook('val2')); testHooks.push(makeHook(), makeHook('val1'), makeHook('val2'));
assert.deepEqual(hooks.callFirst(hookName), ['val1']); assert.deepEqual(hooks.callFirst(hookName), ['val1']);
}); });
it('skips values that do not satisfy predicate (undefined)', async function () { it('skips values that do not satisfy predicate (undefined)', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook('val1')); testHooks.push(makeHook(), makeHook('val1'));
assert.deepEqual(hooks.callFirst(hookName), ['val1']); assert.deepEqual(hooks.callFirst(hookName), ['val1']);
}); });
it('skips values that do not satisfy predicate (empty list)', async function () { it('skips values that do not satisfy predicate (empty list)', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook([]), makeHook('val1')); testHooks.push(makeHook([]), makeHook('val1'));
assert.deepEqual(hooks.callFirst(hookName), ['val1']); assert.deepEqual(hooks.callFirst(hookName), ['val1']);
}); });
it('null satisifes the predicate', async function () { it('null satisifes the predicate', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(null), makeHook('val1')); testHooks.push(makeHook(null), makeHook('val1'));
assert.deepEqual(hooks.callFirst(hookName), [null]); assert.deepEqual(hooks.callFirst(hookName), [null]);
}); });
it('non-empty arrays are returned unmodified', async function () { it('non-empty arrays are returned unmodified', async function () {
this.timeout(30);
const want = ['val1']; const want = ['val1'];
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(want), makeHook(['val2'])); testHooks.push(makeHook(want), makeHook(['val2']));
@ -465,6 +499,7 @@ describe(__filename, function () {
}); });
it('value can be passed via callback', async function () { it('value can be passed via callback', async function () {
this.timeout(30);
const want = {}; const want = {};
hook.hook_fn = (hn, ctx, cb) => { cb(want); }; hook.hook_fn = (hn, ctx, cb) => { cb(want); };
const got = hooks.callFirst(hookName); const got = hooks.callFirst(hookName);
@ -478,11 +513,13 @@ describe(__filename, function () {
describe('basic behavior', function () { describe('basic behavior', function () {
it('passes hook name', async function () { it('passes hook name', async function () {
this.timeout(30);
hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
await callHookFnAsync(hook); await callHookFnAsync(hook);
}); });
it('passes context', async function () { it('passes context', async function () {
this.timeout(30);
for (const val of ['value', null, undefined]) { for (const val of ['value', null, undefined]) {
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); }; hook.hook_fn = (hn, ctx) => { assert.equal(ctx, val); };
await callHookFnAsync(hook, val); await callHookFnAsync(hook, val);
@ -490,6 +527,7 @@ describe(__filename, function () {
}); });
it('returns the value provided to the callback', async function () { it('returns the value provided to the callback', async function () {
this.timeout(30);
for (const val of ['value', null, undefined]) { for (const val of ['value', null, undefined]) {
hook.hook_fn = (hn, ctx, cb) => { cb(ctx); }; hook.hook_fn = (hn, ctx, cb) => { cb(ctx); };
assert.equal(await callHookFnAsync(hook, val), val); assert.equal(await callHookFnAsync(hook, val), val);
@ -498,6 +536,7 @@ describe(__filename, function () {
}); });
it('returns the value returned by the hook function', async function () { it('returns the value returned by the hook function', async function () {
this.timeout(30);
for (const val of ['value', null, undefined]) { for (const val of ['value', null, undefined]) {
// Must not have the cb parameter otherwise returning undefined will never resolve. // Must not have the cb parameter otherwise returning undefined will never resolve.
hook.hook_fn = (hn, ctx) => ctx; hook.hook_fn = (hn, ctx) => ctx;
@ -507,26 +546,31 @@ describe(__filename, function () {
}); });
it('rejects if it throws an exception', async function () { it('rejects if it throws an exception', async function () {
this.timeout(30);
hook.hook_fn = () => { throw new Error('test exception'); }; hook.hook_fn = () => { throw new Error('test exception'); };
await assert.rejects(callHookFnAsync(hook), {message: 'test exception'}); await assert.rejects(callHookFnAsync(hook), {message: 'test exception'});
}); });
it('rejects if rejected Promise passed to callback', async function () { 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'))); hook.hook_fn = (hn, ctx, cb) => cb(Promise.reject(new Error('test exception')));
await assert.rejects(callHookFnAsync(hook), {message: 'test exception'}); await assert.rejects(callHookFnAsync(hook), {message: 'test exception'});
}); });
it('rejects if rejected Promise returned', async function () { it('rejects if rejected Promise returned', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx, cb) => Promise.reject(new Error('test exception')); hook.hook_fn = (hn, ctx, cb) => Promise.reject(new Error('test exception'));
await assert.rejects(callHookFnAsync(hook), {message: 'test exception'}); await assert.rejects(callHookFnAsync(hook), {message: 'test exception'});
}); });
it('callback returns undefined', async function () { it('callback returns undefined', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); }; hook.hook_fn = (hn, ctx, cb) => { assert.equal(cb('foo'), undefined); };
await callHookFnAsync(hook); await callHookFnAsync(hook);
}); });
it('checks for deprecation', async function () { it('checks for deprecation', async function () {
this.timeout(30);
sinon.stub(console, 'warn'); sinon.stub(console, 'warn');
hooks.deprecationNotices[hookName] = 'test deprecation'; hooks.deprecationNotices[hookName] = 'test deprecation';
await callHookFnAsync(hook); await callHookFnAsync(hook);
@ -619,6 +663,7 @@ describe(__filename, function () {
for (const tc of supportedSyncHookFunctions.concat(supportedHookFunctions)) { for (const tc of supportedSyncHookFunctions.concat(supportedHookFunctions)) {
it(tc.name, async function () { it(tc.name, async function () {
this.timeout(30);
sinon.stub(console, 'warn'); sinon.stub(console, 'warn');
sinon.stub(console, 'error'); sinon.stub(console, 'error');
hook.hook_fn = tc.fn; hook.hook_fn = tc.fn;
@ -766,6 +811,7 @@ describe(__filename, function () {
if (step1.name.startsWith('return ') || step1.name === 'throw') continue; if (step1.name.startsWith('return ') || step1.name === 'throw') continue;
for (const step2 of behaviors) { for (const step2 of behaviors) {
it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () { it(`${step1.name} then ${step2.name} (diff. outcomes) -> log+throw`, async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx, cb) => { hook.hook_fn = (hn, ctx, cb) => {
step1.fn(cb, new Error(ctx.ret1), ctx.ret1); step1.fn(cb, new Error(ctx.ret1), ctx.ret1);
return step2.fn(cb, new Error(ctx.ret2), ctx.ret2); return step2.fn(cb, new Error(ctx.ret2), ctx.ret2);
@ -819,6 +865,7 @@ describe(__filename, function () {
if (step1.rejects !== step2.rejects) continue; if (step1.rejects !== step2.rejects) continue;
it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () { it(`${step1.name} then ${step2.name} (same outcome) -> only log`, async function () {
this.timeout(30);
const err = new Error('val'); const err = new Error('val');
hook.hook_fn = (hn, ctx, cb) => { hook.hook_fn = (hn, ctx, cb) => {
step1.fn(cb, err, 'val'); step1.fn(cb, err, 'val');
@ -844,6 +891,7 @@ describe(__filename, function () {
describe('hooks.aCallAll', function () { describe('hooks.aCallAll', function () {
describe('basic behavior', function () { describe('basic behavior', function () {
it('calls all asynchronously, returns values in order', async 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. testHooks.length = 0; // Delete the boilerplate hook -- this test doesn't use it.
let nextIndex = 0; let nextIndex = 0;
const hookPromises = []; const hookPromises = [];
@ -878,21 +926,25 @@ describe(__filename, function () {
}); });
it('passes hook name', async function () { it('passes hook name', async function () {
this.timeout(30);
hook.hook_fn = async (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = async (hn) => { assert.equal(hn, hookName); };
await hooks.aCallAll(hookName); await hooks.aCallAll(hookName);
}); });
it('undefined context -> {}', async function () { it('undefined context -> {}', async function () {
this.timeout(30);
hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); };
await hooks.aCallAll(hookName); await hooks.aCallAll(hookName);
}); });
it('null context -> {}', async function () { it('null context -> {}', async function () {
this.timeout(30);
hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); };
await hooks.aCallAll(hookName, null); await hooks.aCallAll(hookName, null);
}); });
it('context unmodified', async function () { it('context unmodified', async function () {
this.timeout(30);
const wantContext = {}; const wantContext = {};
hook.hook_fn = async (hn, ctx) => { assert.equal(ctx, wantContext); }; hook.hook_fn = async (hn, ctx) => { assert.equal(ctx, wantContext); };
await hooks.aCallAll(hookName, wantContext); await hooks.aCallAll(hookName, wantContext);
@ -901,11 +953,13 @@ describe(__filename, function () {
describe('aCallAll callback', function () { describe('aCallAll callback', function () {
it('exception in callback rejects', async function () { it('exception in callback rejects', async function () {
this.timeout(30);
const p = hooks.aCallAll(hookName, {}, () => { throw new Error('test exception'); }); const p = hooks.aCallAll(hookName, {}, () => { throw new Error('test exception'); });
await assert.rejects(p, {message: 'test exception'}); await assert.rejects(p, {message: 'test exception'});
}); });
it('propagates error on exception', async function () { it('propagates error on exception', async function () {
this.timeout(30);
hook.hook_fn = () => { throw new Error('test exception'); }; hook.hook_fn = () => { throw new Error('test exception'); };
await hooks.aCallAll(hookName, {}, (err) => { await hooks.aCallAll(hookName, {}, (err) => {
assert(err instanceof Error); assert(err instanceof Error);
@ -914,12 +968,14 @@ describe(__filename, function () {
}); });
it('propagages null error on success', async function () { it('propagages null error on success', async function () {
this.timeout(30);
await hooks.aCallAll(hookName, {}, (err) => { await hooks.aCallAll(hookName, {}, (err) => {
assert(err == null, `got non-null error: ${err}`); assert(err == null, `got non-null error: ${err}`);
}); });
}); });
it('propagages results on success', async function () { it('propagages results on success', async function () {
this.timeout(30);
hook.hook_fn = () => 'val'; hook.hook_fn = () => 'val';
await hooks.aCallAll(hookName, {}, (err, results) => { await hooks.aCallAll(hookName, {}, (err, results) => {
assert.deepEqual(results, ['val']); assert.deepEqual(results, ['val']);
@ -927,40 +983,47 @@ describe(__filename, function () {
}); });
it('returns callback return value', async function () { it('returns callback return value', async function () {
this.timeout(30);
assert.equal(await hooks.aCallAll(hookName, {}, () => 'val'), 'val'); assert.equal(await hooks.aCallAll(hookName, {}, () => 'val'), 'val');
}); });
}); });
describe('result processing', function () { describe('result processing', function () {
it('no registered hooks (undefined) -> []', async function () { it('no registered hooks (undefined) -> []', async function () {
this.timeout(30);
delete plugins.hooks[hookName]; delete plugins.hooks[hookName];
assert.deepEqual(await hooks.aCallAll(hookName), []); assert.deepEqual(await hooks.aCallAll(hookName), []);
}); });
it('no registered hooks (empty list) -> []', async function () { it('no registered hooks (empty list) -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
assert.deepEqual(await hooks.aCallAll(hookName), []); assert.deepEqual(await hooks.aCallAll(hookName), []);
}); });
it('flattens one level', async function () { it('flattens one level', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]])); testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]]));
assert.deepEqual(await hooks.aCallAll(hookName), [1, 2, [3]]); assert.deepEqual(await hooks.aCallAll(hookName), [1, 2, [3]]);
}); });
it('filters out undefined', async function () { it('filters out undefined', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]), makeHook(Promise.resolve())); testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]), makeHook(Promise.resolve()));
assert.deepEqual(await hooks.aCallAll(hookName), [2, [3]]); assert.deepEqual(await hooks.aCallAll(hookName), [2, [3]]);
}); });
it('preserves null', async function () { it('preserves null', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(null), makeHook([2]), makeHook(Promise.resolve(null))); testHooks.push(makeHook(null), makeHook([2]), makeHook(Promise.resolve(null)));
assert.deepEqual(await hooks.aCallAll(hookName), [null, 2, null]); assert.deepEqual(await hooks.aCallAll(hookName), [null, 2, null]);
}); });
it('all undefined -> []', async function () { it('all undefined -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook(Promise.resolve())); testHooks.push(makeHook(), makeHook(Promise.resolve()));
assert.deepEqual(await hooks.aCallAll(hookName), []); assert.deepEqual(await hooks.aCallAll(hookName), []);
@ -971,6 +1034,7 @@ describe(__filename, function () {
describe('hooks.callAllSerial', function () { describe('hooks.callAllSerial', function () {
describe('basic behavior', function () { describe('basic behavior', function () {
it('calls all asynchronously, serially, in order', async function () { it('calls all asynchronously, serially, in order', async function () {
this.timeout(30);
const gotCalls = []; const gotCalls = [];
testHooks.length = 0; testHooks.length = 0;
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
@ -993,21 +1057,25 @@ describe(__filename, function () {
}); });
it('passes hook name', async function () { it('passes hook name', async function () {
this.timeout(30);
hook.hook_fn = async (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = async (hn) => { assert.equal(hn, hookName); };
await hooks.callAllSerial(hookName); await hooks.callAllSerial(hookName);
}); });
it('undefined context -> {}', async function () { it('undefined context -> {}', async function () {
this.timeout(30);
hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); };
await hooks.callAllSerial(hookName); await hooks.callAllSerial(hookName);
}); });
it('null context -> {}', async function () { it('null context -> {}', async function () {
this.timeout(30);
hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = async (hn, ctx) => { assert.deepEqual(ctx, {}); };
await hooks.callAllSerial(hookName, null); await hooks.callAllSerial(hookName, null);
}); });
it('context unmodified', async function () { it('context unmodified', async function () {
this.timeout(30);
const wantContext = {}; const wantContext = {};
hook.hook_fn = async (hn, ctx) => { assert.equal(ctx, wantContext); }; hook.hook_fn = async (hn, ctx) => { assert.equal(ctx, wantContext); };
await hooks.callAllSerial(hookName, wantContext); await hooks.callAllSerial(hookName, wantContext);
@ -1016,34 +1084,40 @@ describe(__filename, function () {
describe('result processing', function () { describe('result processing', function () {
it('no registered hooks (undefined) -> []', async function () { it('no registered hooks (undefined) -> []', async function () {
this.timeout(30);
delete plugins.hooks[hookName]; delete plugins.hooks[hookName];
assert.deepEqual(await hooks.callAllSerial(hookName), []); assert.deepEqual(await hooks.callAllSerial(hookName), []);
}); });
it('no registered hooks (empty list) -> []', async function () { it('no registered hooks (empty list) -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
assert.deepEqual(await hooks.callAllSerial(hookName), []); assert.deepEqual(await hooks.callAllSerial(hookName), []);
}); });
it('flattens one level', async function () { it('flattens one level', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]])); testHooks.push(makeHook(1), makeHook([2]), makeHook([[3]]));
assert.deepEqual(await hooks.callAllSerial(hookName), [1, 2, [3]]); assert.deepEqual(await hooks.callAllSerial(hookName), [1, 2, [3]]);
}); });
it('filters out undefined', async function () { it('filters out undefined', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]), makeHook(Promise.resolve())); testHooks.push(makeHook(), makeHook([2]), makeHook([[3]]), makeHook(Promise.resolve()));
assert.deepEqual(await hooks.callAllSerial(hookName), [2, [3]]); assert.deepEqual(await hooks.callAllSerial(hookName), [2, [3]]);
}); });
it('preserves null', async function () { it('preserves null', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(null), makeHook([2]), makeHook(Promise.resolve(null))); testHooks.push(makeHook(null), makeHook([2]), makeHook(Promise.resolve(null)));
assert.deepEqual(await hooks.callAllSerial(hookName), [null, 2, null]); assert.deepEqual(await hooks.callAllSerial(hookName), [null, 2, null]);
}); });
it('all undefined -> []', async function () { it('all undefined -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook(Promise.resolve())); testHooks.push(makeHook(), makeHook(Promise.resolve()));
assert.deepEqual(await hooks.callAllSerial(hookName), []); assert.deepEqual(await hooks.callAllSerial(hookName), []);
@ -1053,37 +1127,44 @@ describe(__filename, function () {
describe('hooks.aCallFirst', function () { describe('hooks.aCallFirst', function () {
it('no registered hooks (undefined) -> []', async function () { it('no registered hooks (undefined) -> []', async function () {
this.timeout(30);
delete plugins.hooks.testHook; delete plugins.hooks.testHook;
assert.deepEqual(await hooks.aCallFirst(hookName), []); assert.deepEqual(await hooks.aCallFirst(hookName), []);
}); });
it('no registered hooks (empty list) -> []', async function () { it('no registered hooks (empty list) -> []', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
assert.deepEqual(await hooks.aCallFirst(hookName), []); assert.deepEqual(await hooks.aCallFirst(hookName), []);
}); });
it('passes hook name => {}', async function () { it('passes hook name => {}', async function () {
this.timeout(30);
hook.hook_fn = (hn) => { assert.equal(hn, hookName); }; hook.hook_fn = (hn) => { assert.equal(hn, hookName); };
await hooks.aCallFirst(hookName); await hooks.aCallFirst(hookName);
}); });
it('undefined context => {}', async function () { it('undefined context => {}', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
await hooks.aCallFirst(hookName); await hooks.aCallFirst(hookName);
}); });
it('null context => {}', async function () { it('null context => {}', async function () {
this.timeout(30);
hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); }; hook.hook_fn = (hn, ctx) => { assert.deepEqual(ctx, {}); };
await hooks.aCallFirst(hookName, null); await hooks.aCallFirst(hookName, null);
}); });
it('context unmodified', async function () { it('context unmodified', async function () {
this.timeout(30);
const wantContext = {}; const wantContext = {};
hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); }; hook.hook_fn = (hn, ctx) => { assert.equal(ctx, wantContext); };
await hooks.aCallFirst(hookName, wantContext); await hooks.aCallFirst(hookName, wantContext);
}); });
it('default predicate: predicate never satisfied -> calls all in order', async function () { it('default predicate: predicate never satisfied -> calls all in order', async function () {
this.timeout(30);
const gotCalls = []; const gotCalls = [];
testHooks.length = 0; testHooks.length = 0;
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
@ -1096,6 +1177,7 @@ describe(__filename, function () {
}); });
it('calls hook functions serially', async function () { it('calls hook functions serially', async function () {
this.timeout(30);
const gotCalls = []; const gotCalls = [];
testHooks.length = 0; testHooks.length = 0;
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
@ -1118,30 +1200,35 @@ describe(__filename, function () {
}); });
it('default predicate: stops when satisfied', async function () { it('default predicate: stops when satisfied', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook('val1'), makeHook('val2')); testHooks.push(makeHook(), makeHook('val1'), makeHook('val2'));
assert.deepEqual(await hooks.aCallFirst(hookName), ['val1']); assert.deepEqual(await hooks.aCallFirst(hookName), ['val1']);
}); });
it('default predicate: skips values that do not satisfy (undefined)', async function () { it('default predicate: skips values that do not satisfy (undefined)', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(), makeHook('val1')); testHooks.push(makeHook(), makeHook('val1'));
assert.deepEqual(await hooks.aCallFirst(hookName), ['val1']); assert.deepEqual(await hooks.aCallFirst(hookName), ['val1']);
}); });
it('default predicate: skips values that do not satisfy (empty list)', async function () { it('default predicate: skips values that do not satisfy (empty list)', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook([]), makeHook('val1')); testHooks.push(makeHook([]), makeHook('val1'));
assert.deepEqual(await hooks.aCallFirst(hookName), ['val1']); assert.deepEqual(await hooks.aCallFirst(hookName), ['val1']);
}); });
it('default predicate: null satisifes', async function () { it('default predicate: null satisifes', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(null), makeHook('val1')); testHooks.push(makeHook(null), makeHook('val1'));
assert.deepEqual(await hooks.aCallFirst(hookName), [null]); assert.deepEqual(await hooks.aCallFirst(hookName), [null]);
}); });
it('custom predicate: called for each hook function', async function () { it('custom predicate: called for each hook function', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(0), makeHook(1), makeHook(2)); testHooks.push(makeHook(0), makeHook(1), makeHook(2));
let got = 0; let got = 0;
@ -1150,6 +1237,7 @@ describe(__filename, function () {
}); });
it('custom predicate: boolean false/true continues/stops iteration', async function () { it('custom predicate: boolean false/true continues/stops iteration', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(1), makeHook(2), makeHook(3)); testHooks.push(makeHook(1), makeHook(2), makeHook(3));
let nCall = 0; let nCall = 0;
@ -1162,6 +1250,7 @@ describe(__filename, function () {
}); });
it('custom predicate: non-boolean falsy/truthy continues/stops iteration', async function () { it('custom predicate: non-boolean falsy/truthy continues/stops iteration', async function () {
this.timeout(30);
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(1), makeHook(2), makeHook(3)); testHooks.push(makeHook(1), makeHook(2), makeHook(3));
let nCall = 0; let nCall = 0;
@ -1174,6 +1263,7 @@ describe(__filename, function () {
}); });
it('custom predicate: array value passed unmodified to predicate', async function () { it('custom predicate: array value passed unmodified to predicate', async function () {
this.timeout(30);
const want = [0]; const want = [0];
hook.hook_fn = () => want; hook.hook_fn = () => want;
const predicate = (got) => { assert.equal(got, want); }; // Note: *NOT* deepEqual! const predicate = (got) => { assert.equal(got, want); }; // Note: *NOT* deepEqual!
@ -1181,17 +1271,20 @@ describe(__filename, function () {
}); });
it('custom predicate: normalized value passed to predicate (undefined)', async function () { it('custom predicate: normalized value passed to predicate (undefined)', async function () {
this.timeout(30);
const predicate = (got) => { assert.deepEqual(got, []); }; const predicate = (got) => { assert.deepEqual(got, []); };
await hooks.aCallFirst(hookName, null, null, predicate); await hooks.aCallFirst(hookName, null, null, predicate);
}); });
it('custom predicate: normalized value passed to predicate (null)', async function () { it('custom predicate: normalized value passed to predicate (null)', async function () {
this.timeout(30);
hook.hook_fn = () => null; hook.hook_fn = () => null;
const predicate = (got) => { assert.deepEqual(got, [null]); }; const predicate = (got) => { assert.deepEqual(got, [null]); };
await hooks.aCallFirst(hookName, null, null, predicate); await hooks.aCallFirst(hookName, null, null, predicate);
}); });
it('non-empty arrays are returned unmodified', async function () { it('non-empty arrays are returned unmodified', async function () {
this.timeout(30);
const want = ['val1']; const want = ['val1'];
testHooks.length = 0; testHooks.length = 0;
testHooks.push(makeHook(want), makeHook(['val2'])); testHooks.push(makeHook(want), makeHook(['val2']));
@ -1199,6 +1292,7 @@ describe(__filename, function () {
}); });
it('value can be passed via callback', async function () { it('value can be passed via callback', async function () {
this.timeout(30);
const want = {}; const want = {};
hook.hook_fn = (hn, ctx, cb) => { cb(want); }; hook.hook_fn = (hn, ctx, cb) => { cb(want); };
const got = await hooks.aCallFirst(hookName); const got = await hooks.aCallFirst(hookName);

View file

@ -89,6 +89,7 @@ const handshake = async (socket, padID) => {
}; };
describe(__filename, function () { describe(__filename, function () {
this.timeout(30000);
let agent; let agent;
let authorize; let authorize;
const backups = {}; const backups = {};
@ -136,23 +137,27 @@ describe(__filename, function () {
describe('Normal accesses', function () { describe('Normal accesses', function () {
it('!authn anonymous cookie /p/pad -> 200, ok', async function () { it('!authn anonymous cookie /p/pad -> 200, ok', async function () {
this.timeout(600);
const res = await agent.get('/p/pad').expect(200); const res = await agent.get('/p/pad').expect(200);
socket = await connect(res); socket = await connect(res);
const clientVars = await handshake(socket, 'pad'); const clientVars = await handshake(socket, 'pad');
assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.type, 'CLIENT_VARS');
}); });
it('!authn !cookie -> ok', async function () { it('!authn !cookie -> ok', async function () {
this.timeout(400);
socket = await connect(null); socket = await connect(null);
const clientVars = await handshake(socket, 'pad'); const clientVars = await handshake(socket, 'pad');
assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.type, 'CLIENT_VARS');
}); });
it('!authn user /p/pad -> 200, ok', async function () { 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); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
const clientVars = await handshake(socket, 'pad'); const clientVars = await handshake(socket, 'pad');
assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.type, 'CLIENT_VARS');
}); });
it('authn user /p/pad -> 200, ok', async function () { it('authn user /p/pad -> 200, ok', async function () {
this.timeout(400);
settings.requireAuthentication = true; settings.requireAuthentication = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -160,6 +165,7 @@ describe(__filename, function () {
assert.equal(clientVars.type, 'CLIENT_VARS'); assert.equal(clientVars.type, 'CLIENT_VARS');
}); });
it('authz user /p/pad -> 200, ok', async function () { it('authz user /p/pad -> 200, ok', async function () {
this.timeout(400);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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'); assert.equal(clientVars.type, 'CLIENT_VARS');
}); });
it('supports pad names with characters that must be percent-encoded', async function () { it('supports pad names with characters that must be percent-encoded', async function () {
this.timeout(400);
settings.requireAuthentication = true; settings.requireAuthentication = true;
// requireAuthorization is set to true here to guarantee that the user's padAuthorizations // 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 // 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 () { describe('Abnormal access attempts', function () {
it('authn anonymous /p/pad -> 401, error', async function () { it('authn anonymous /p/pad -> 401, error', async function () {
this.timeout(400);
settings.requireAuthentication = true; settings.requireAuthentication = true;
const res = await agent.get('/p/pad').expect(401); const res = await agent.get('/p/pad').expect(401);
// Despite the 401, try to create the pad via a socket.io connection anyway. // 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'); assert.equal(message.accessStatus, 'deny');
}); });
it('authn !cookie -> error', async function () { it('authn !cookie -> error', async function () {
this.timeout(400);
settings.requireAuthentication = true; settings.requireAuthentication = true;
socket = await connect(null); socket = await connect(null);
const message = await handshake(socket, 'pad'); const message = await handshake(socket, 'pad');
assert.equal(message.accessStatus, 'deny'); assert.equal(message.accessStatus, 'deny');
}); });
it('authorization bypass attempt -> error', async function () { it('authorization bypass attempt -> error', async function () {
this.timeout(400);
// Only allowed to access /p/pad. // Only allowed to access /p/pad.
authorize = (req) => req.path === '/p/pad'; authorize = (req) => req.path === '/p/pad';
settings.requireAuthentication = true; settings.requireAuthentication = true;
@ -218,6 +228,7 @@ describe(__filename, function () {
}); });
it("level='create' -> can create", async function () { it("level='create' -> can create", async function () {
this.timeout(400);
authorize = () => 'create'; authorize = () => 'create';
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -226,6 +237,7 @@ describe(__filename, function () {
assert.equal(clientVars.data.readonly, false); assert.equal(clientVars.data.readonly, false);
}); });
it('level=true -> can create', async function () { it('level=true -> can create', async function () {
this.timeout(400);
authorize = () => true; authorize = () => true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -234,6 +246,7 @@ describe(__filename, function () {
assert.equal(clientVars.data.readonly, false); assert.equal(clientVars.data.readonly, false);
}); });
it("level='modify' -> can modify", async function () { it("level='modify' -> can modify", async function () {
this.timeout(400);
await padManager.getPad('pad'); // Create the pad. await padManager.getPad('pad'); // Create the pad.
authorize = () => 'modify'; authorize = () => 'modify';
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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); assert.equal(clientVars.data.readonly, false);
}); });
it("level='create' settings.editOnly=true -> unable to create", async function () { it("level='create' settings.editOnly=true -> unable to create", async function () {
this.timeout(400);
authorize = () => 'create'; authorize = () => 'create';
settings.editOnly = true; settings.editOnly = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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'); assert.equal(message.accessStatus, 'deny');
}); });
it("level='modify' settings.editOnly=false -> unable to create", async function () { it("level='modify' settings.editOnly=false -> unable to create", async function () {
this.timeout(400);
authorize = () => 'modify'; authorize = () => 'modify';
settings.editOnly = false; settings.editOnly = false;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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'); assert.equal(message.accessStatus, 'deny');
}); });
it("level='readOnly' -> unable to create", async function () { it("level='readOnly' -> unable to create", async function () {
this.timeout(400);
authorize = () => 'readOnly'; authorize = () => 'readOnly';
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -266,6 +282,7 @@ describe(__filename, function () {
assert.equal(message.accessStatus, 'deny'); assert.equal(message.accessStatus, 'deny');
}); });
it("level='readOnly' -> unable to modify", async function () { it("level='readOnly' -> unable to modify", async function () {
this.timeout(400);
await padManager.getPad('pad'); // Create the pad. await padManager.getPad('pad'); // Create the pad.
authorize = () => 'readOnly'; authorize = () => 'readOnly';
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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 () { it('user.canCreate = true -> can create and modify', async function () {
this.timeout(400);
settings.users.user.canCreate = true; settings.users.user.canCreate = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -290,6 +308,7 @@ describe(__filename, function () {
assert.equal(clientVars.data.readonly, false); assert.equal(clientVars.data.readonly, false);
}); });
it('user.canCreate = false -> unable to create', async function () { it('user.canCreate = false -> unable to create', async function () {
this.timeout(400);
settings.users.user.canCreate = false; settings.users.user.canCreate = false;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -297,6 +316,7 @@ describe(__filename, function () {
assert.equal(message.accessStatus, 'deny'); assert.equal(message.accessStatus, 'deny');
}); });
it('user.readOnly = true -> unable to create', async function () { it('user.readOnly = true -> unable to create', async function () {
this.timeout(400);
settings.users.user.readOnly = true; settings.users.user.readOnly = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -304,6 +324,7 @@ describe(__filename, function () {
assert.equal(message.accessStatus, 'deny'); assert.equal(message.accessStatus, 'deny');
}); });
it('user.readOnly = true -> unable to modify', async function () { it('user.readOnly = true -> unable to modify', async function () {
this.timeout(400);
await padManager.getPad('pad'); // Create the pad. await padManager.getPad('pad'); // Create the pad.
settings.users.user.readOnly = true; settings.users.user.readOnly = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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); assert.equal(clientVars.data.readonly, true);
}); });
it('user.readOnly = false -> can create and modify', async function () { it('user.readOnly = false -> can create and modify', async function () {
this.timeout(400);
settings.users.user.readOnly = false; settings.users.user.readOnly = false;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200);
socket = await connect(res); socket = await connect(res);
@ -321,6 +343,7 @@ describe(__filename, function () {
assert.equal(clientVars.data.readonly, false); assert.equal(clientVars.data.readonly, false);
}); });
it('user.readOnly = true, user.canCreate = true -> unable to create', async function () { it('user.readOnly = true, user.canCreate = true -> unable to create', async function () {
this.timeout(400);
settings.users.user.canCreate = true; settings.users.user.canCreate = true;
settings.users.user.readOnly = true; settings.users.user.readOnly = true;
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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 () { it('authorize hook does not elevate level from user settings', async function () {
this.timeout(400);
settings.users.user.readOnly = true; settings.users.user.readOnly = true;
authorize = () => 'create'; authorize = () => 'create';
const res = await agent.get('/p/pad').auth('user', 'user-password').expect(200); 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'); assert.equal(message.accessStatus, 'deny');
}); });
it('user settings does not elevate level from authorize hook', async function () { it('user settings does not elevate level from authorize hook', async function () {
this.timeout(400);
settings.users.user.readOnly = false; settings.users.user.readOnly = false;
settings.users.user.canCreate = true; settings.users.user.canCreate = true;
authorize = () => 'readOnly'; authorize = () => 'readOnly';

View file

@ -2,6 +2,7 @@ const common = require('../common');
const settings = require('../../../node/utils/Settings'); const settings = require('../../../node/utils/Settings');
describe(__filename, function () { describe(__filename, function () {
this.timeout(30000);
let agent; let agent;
const backups = {}; const backups = {};
before(async function () { agent = await common.init(); }); before(async function () { agent = await common.init(); });
@ -19,6 +20,7 @@ describe(__filename, function () {
describe('/javascript', function () { describe('/javascript', function () {
it('/javascript -> 200', async function () { it('/javascript -> 200', async function () {
this.timeout(200);
await agent.get('/javascript').expect(200); await agent.get('/javascript').expect(200);
}); });
}); });

View file

@ -6,6 +6,7 @@ const plugins = require('../../../static/js/pluginfw/plugin_defs');
const settings = require('../../../node/utils/Settings'); const settings = require('../../../node/utils/Settings');
describe(__filename, function () { describe(__filename, function () {
this.timeout(30000);
let agent; let agent;
const backups = {}; const backups = {};
const authHookNames = ['preAuthorize', 'authenticate', 'authorize']; const authHookNames = ['preAuthorize', 'authenticate', 'authorize'];
@ -42,56 +43,67 @@ describe(__filename, function () {
describe('webaccess: without plugins', function () { describe('webaccess: without plugins', function () {
it('!authn !authz anonymous / -> 200', async function () { it('!authn !authz anonymous / -> 200', async function () {
this.timeout(150);
settings.requireAuthentication = false; settings.requireAuthentication = false;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/').expect(200); await agent.get('/').expect(200);
}); });
it('!authn !authz anonymous /admin/ -> 401', async function () { it('!authn !authz anonymous /admin/ -> 401', async function () {
this.timeout(100);
settings.requireAuthentication = false; settings.requireAuthentication = false;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/admin/').expect(401); await agent.get('/admin/').expect(401);
}); });
it('authn !authz anonymous / -> 401', async function () { it('authn !authz anonymous / -> 401', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/').expect(401); await agent.get('/').expect(401);
}); });
it('authn !authz user / -> 200', async function () { it('authn !authz user / -> 200', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/').auth('user', 'user-password').expect(200); await agent.get('/').auth('user', 'user-password').expect(200);
}); });
it('authn !authz user /admin/ -> 403', async function () { it('authn !authz user /admin/ -> 403', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/admin/').auth('user', 'user-password').expect(403); await agent.get('/admin/').auth('user', 'user-password').expect(403);
}); });
it('authn !authz admin / -> 200', async function () { it('authn !authz admin / -> 200', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/').auth('admin', 'admin-password').expect(200); await agent.get('/').auth('admin', 'admin-password').expect(200);
}); });
it('authn !authz admin /admin/ -> 200', async function () { it('authn !authz admin /admin/ -> 200', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/admin/').auth('admin', 'admin-password').expect(200); await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
}); });
it('authn authz user / -> 403', async function () { it('authn authz user / -> 403', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
await agent.get('/').auth('user', 'user-password').expect(403); await agent.get('/').auth('user', 'user-password').expect(403);
}); });
it('authn authz user /admin/ -> 403', async function () { it('authn authz user /admin/ -> 403', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
await agent.get('/admin/').auth('user', 'user-password').expect(403); await agent.get('/admin/').auth('user', 'user-password').expect(403);
}); });
it('authn authz admin / -> 200', async function () { it('authn authz admin / -> 200', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
await agent.get('/').auth('admin', 'admin-password').expect(200); await agent.get('/').auth('admin', 'admin-password').expect(200);
}); });
it('authn authz admin /admin/ -> 200', async function () { it('authn authz admin /admin/ -> 200', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
await agent.get('/admin/').auth('admin', 'admin-password').expect(200); 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. // parsing, resulting in successful comparisons against a null or undefined password.
for (const creds of ['admin', 'admin:']) { for (const creds of ['admin', 'admin:']) {
it(`admin password: ${adminPassword} credentials: ${creds}`, async function () { it(`admin password: ${adminPassword} credentials: ${creds}`, async function () {
this.timeout(100);
settings.users.admin.password = adminPassword; settings.users.admin.password = adminPassword;
const encCreds = Buffer.from(creds).toString('base64'); const encCreds = Buffer.from(creds).toString('base64');
await agent.get('/admin/').set('Authorization', `Basic ${encCreds}`).expect(401); await agent.get('/admin/').set('Authorization', `Basic ${encCreds}`).expect(401);
@ -160,11 +173,13 @@ describe(__filename, function () {
}); });
it('defers if it returns []', async function () { it('defers if it returns []', async function () {
this.timeout(100);
await agent.get('/').expect(200); await agent.get('/').expect(200);
// Note: The preAuthorize hook always runs even if requireAuthorization is false. // Note: The preAuthorize hook always runs even if requireAuthorization is false.
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
}); });
it('bypasses authenticate and authorize hooks when true is returned', async function () { it('bypasses authenticate and authorize hooks when true is returned', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
handlers.preAuthorize[0].innerHandle = () => [true]; handlers.preAuthorize[0].innerHandle = () => [true];
@ -172,6 +187,7 @@ describe(__filename, function () {
assert.deepEqual(callOrder, ['preAuthorize_0']); assert.deepEqual(callOrder, ['preAuthorize_0']);
}); });
it('bypasses authenticate and authorize hooks when false is returned', async function () { it('bypasses authenticate and authorize hooks when false is returned', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
handlers.preAuthorize[0].innerHandle = () => [false]; handlers.preAuthorize[0].innerHandle = () => [false];
@ -179,12 +195,14 @@ describe(__filename, function () {
assert.deepEqual(callOrder, ['preAuthorize_0']); assert.deepEqual(callOrder, ['preAuthorize_0']);
}); });
it('bypasses authenticate and authorize hooks for static content, defers', async function () { it('bypasses authenticate and authorize hooks for static content, defers', async function () {
this.timeout(100);
settings.requireAuthentication = true; settings.requireAuthentication = true;
settings.requireAuthorization = true; settings.requireAuthorization = true;
await agent.get('/static/robots.txt').expect(200); await agent.get('/static/robots.txt').expect(200);
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
}); });
it('cannot grant access to /admin', async function () { it('cannot grant access to /admin', async function () {
this.timeout(100);
handlers.preAuthorize[0].innerHandle = () => [true]; handlers.preAuthorize[0].innerHandle = () => [true];
await agent.get('/admin/').expect(401); await agent.get('/admin/').expect(401);
// Notes: // Notes:
@ -198,11 +216,13 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('can deny access to /admin', async function () { it('can deny access to /admin', async function () {
this.timeout(100);
handlers.preAuthorize[0].innerHandle = () => [false]; handlers.preAuthorize[0].innerHandle = () => [false];
await agent.get('/admin/').auth('admin', 'admin-password').expect(403); await agent.get('/admin/').auth('admin', 'admin-password').expect(403);
assert.deepEqual(callOrder, ['preAuthorize_0']); assert.deepEqual(callOrder, ['preAuthorize_0']);
}); });
it('runs preAuthzFailure hook when access is denied', async function () { it('runs preAuthzFailure hook when access is denied', async function () {
this.timeout(100);
handlers.preAuthorize[0].innerHandle = () => [false]; handlers.preAuthorize[0].innerHandle = () => [false];
let called = false; let called = false;
plugins.hooks.preAuthzFailure = [makeHook('preAuthzFailure', (hookName, {req, res}, cb) => { plugins.hooks.preAuthzFailure = [makeHook('preAuthzFailure', (hookName, {req, res}, cb) => {
@ -218,6 +238,7 @@ describe(__filename, function () {
assert(called); assert(called);
}); });
it('returns 500 if an exception is thrown', async function () { it('returns 500 if an exception is thrown', async function () {
this.timeout(100);
handlers.preAuthorize[0].innerHandle = () => { throw new Error('exception test'); }; handlers.preAuthorize[0].innerHandle = () => { throw new Error('exception test'); };
await agent.get('/').expect(500); await agent.get('/').expect(500);
}); });
@ -230,11 +251,13 @@ describe(__filename, function () {
}); });
it('is not called if !requireAuthentication and not /admin/*', async function () { it('is not called if !requireAuthentication and not /admin/*', async function () {
this.timeout(100);
settings.requireAuthentication = false; settings.requireAuthentication = false;
await agent.get('/').expect(200); await agent.get('/').expect(200);
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
}); });
it('is called if !requireAuthentication and /admin/*', async function () { it('is called if !requireAuthentication and /admin/*', async function () {
this.timeout(100);
settings.requireAuthentication = false; settings.requireAuthentication = false;
await agent.get('/admin/').expect(401); await agent.get('/admin/').expect(401);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
@ -243,6 +266,7 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('defers if empty list returned', async function () { it('defers if empty list returned', async function () {
this.timeout(100);
await agent.get('/').expect(401); await agent.get('/').expect(401);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
'preAuthorize_1', 'preAuthorize_1',
@ -250,18 +274,21 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('does not defer if return [true], 200', async function () { it('does not defer if return [true], 200', async function () {
this.timeout(100);
handlers.authenticate[0].innerHandle = (req) => { req.session.user = {}; return [true]; }; handlers.authenticate[0].innerHandle = (req) => { req.session.user = {}; return [true]; };
await agent.get('/').expect(200); await agent.get('/').expect(200);
// Note: authenticate_1 was not called because authenticate_0 handled it. // Note: authenticate_1 was not called because authenticate_0 handled it.
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
}); });
it('does not defer if return [false], 401', async function () { it('does not defer if return [false], 401', async function () {
this.timeout(100);
handlers.authenticate[0].innerHandle = (req) => [false]; handlers.authenticate[0].innerHandle = (req) => [false];
await agent.get('/').expect(401); await agent.get('/').expect(401);
// Note: authenticate_1 was not called because authenticate_0 handled it. // Note: authenticate_1 was not called because authenticate_0 handled it.
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
}); });
it('falls back to HTTP basic auth', async function () { it('falls back to HTTP basic auth', async function () {
this.timeout(100);
await agent.get('/').auth('user', 'user-password').expect(200); await agent.get('/').auth('user', 'user-password').expect(200);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
'preAuthorize_1', 'preAuthorize_1',
@ -269,6 +296,7 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('passes settings.users in context', async function () { it('passes settings.users in context', async function () {
this.timeout(100);
handlers.authenticate[0].checkContext = ({users}) => { handlers.authenticate[0].checkContext = ({users}) => {
assert.equal(users, settings.users); assert.equal(users, settings.users);
}; };
@ -279,6 +307,7 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('passes user, password in context if provided', async function () { it('passes user, password in context if provided', async function () {
this.timeout(100);
handlers.authenticate[0].checkContext = ({username, password}) => { handlers.authenticate[0].checkContext = ({username, password}) => {
assert.equal(username, 'user'); assert.equal(username, 'user');
assert.equal(password, 'user-password'); assert.equal(password, 'user-password');
@ -290,6 +319,7 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('does not pass user, password in context if not provided', async function () { it('does not pass user, password in context if not provided', async function () {
this.timeout(100);
handlers.authenticate[0].checkContext = ({username, password}) => { handlers.authenticate[0].checkContext = ({username, password}) => {
assert(username == null); assert(username == null);
assert(password == null); assert(password == null);
@ -301,11 +331,13 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('errors if req.session.user is not created', async function () { it('errors if req.session.user is not created', async function () {
this.timeout(100);
handlers.authenticate[0].innerHandle = () => [true]; handlers.authenticate[0].innerHandle = () => [true];
await agent.get('/').expect(500); await agent.get('/').expect(500);
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']);
}); });
it('returns 500 if an exception is thrown', async function () { it('returns 500 if an exception is thrown', async function () {
this.timeout(100);
handlers.authenticate[0].innerHandle = () => { throw new Error('exception test'); }; handlers.authenticate[0].innerHandle = () => { throw new Error('exception test'); };
await agent.get('/').expect(500); await agent.get('/').expect(500);
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1', 'authenticate_0']); 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 () { it('is not called if !requireAuthorization (non-/admin)', async function () {
this.timeout(100);
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/').auth('user', 'user-password').expect(200); await agent.get('/').auth('user', 'user-password').expect(200);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
@ -327,6 +360,7 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('is not called if !requireAuthorization (/admin)', async function () { it('is not called if !requireAuthorization (/admin)', async function () {
this.timeout(100);
settings.requireAuthorization = false; settings.requireAuthorization = false;
await agent.get('/admin/').auth('admin', 'admin-password').expect(200); await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
@ -335,6 +369,7 @@ describe(__filename, function () {
'authenticate_1']); 'authenticate_1']);
}); });
it('defers if empty list returned', async function () { it('defers if empty list returned', async function () {
this.timeout(100);
await agent.get('/').auth('user', 'user-password').expect(403); await agent.get('/').auth('user', 'user-password').expect(403);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
'preAuthorize_1', 'preAuthorize_1',
@ -344,6 +379,7 @@ describe(__filename, function () {
'authorize_1']); 'authorize_1']);
}); });
it('does not defer if return [true], 200', async function () { it('does not defer if return [true], 200', async function () {
this.timeout(100);
handlers.authorize[0].innerHandle = () => [true]; handlers.authorize[0].innerHandle = () => [true];
await agent.get('/').auth('user', 'user-password').expect(200); await agent.get('/').auth('user', 'user-password').expect(200);
// Note: authorize_1 was not called because authorize_0 handled it. // Note: authorize_1 was not called because authorize_0 handled it.
@ -354,6 +390,7 @@ describe(__filename, function () {
'authorize_0']); 'authorize_0']);
}); });
it('does not defer if return [false], 403', async function () { it('does not defer if return [false], 403', async function () {
this.timeout(100);
handlers.authorize[0].innerHandle = (req) => [false]; handlers.authorize[0].innerHandle = (req) => [false];
await agent.get('/').auth('user', 'user-password').expect(403); await agent.get('/').auth('user', 'user-password').expect(403);
// Note: authorize_1 was not called because authorize_0 handled it. // Note: authorize_1 was not called because authorize_0 handled it.
@ -364,6 +401,7 @@ describe(__filename, function () {
'authorize_0']); 'authorize_0']);
}); });
it('passes req.path in context', async function () { it('passes req.path in context', async function () {
this.timeout(100);
handlers.authorize[0].checkContext = ({resource}) => { handlers.authorize[0].checkContext = ({resource}) => {
assert.equal(resource, '/'); assert.equal(resource, '/');
}; };
@ -376,6 +414,7 @@ describe(__filename, function () {
'authorize_1']); 'authorize_1']);
}); });
it('returns 500 if an exception is thrown', async function () { it('returns 500 if an exception is thrown', async function () {
this.timeout(100);
handlers.authorize[0].innerHandle = () => { throw new Error('exception test'); }; handlers.authorize[0].innerHandle = () => { throw new Error('exception test'); };
await agent.get('/').auth('user', 'user-password').expect(500); await agent.get('/').auth('user', 'user-password').expect(500);
assert.deepEqual(callOrder, ['preAuthorize_0', assert.deepEqual(callOrder, ['preAuthorize_0',
@ -422,12 +461,14 @@ describe(__filename, function () {
// authn failure tests // authn failure tests
it('authn fail, no hooks handle -> 401', async function () { it('authn fail, no hooks handle -> 401', async function () {
this.timeout(100);
await agent.get('/').expect(401); await agent.get('/').expect(401);
assert(handlers.authnFailure.called); assert(handlers.authnFailure.called);
assert(!handlers.authzFailure.called); assert(!handlers.authzFailure.called);
assert(handlers.authFailure.called); assert(handlers.authFailure.called);
}); });
it('authn fail, authnFailure handles', async function () { it('authn fail, authnFailure handles', async function () {
this.timeout(100);
handlers.authnFailure.shouldHandle = true; handlers.authnFailure.shouldHandle = true;
await agent.get('/').expect(200, 'authnFailure'); await agent.get('/').expect(200, 'authnFailure');
assert(handlers.authnFailure.called); assert(handlers.authnFailure.called);
@ -435,6 +476,7 @@ describe(__filename, function () {
assert(!handlers.authFailure.called); assert(!handlers.authFailure.called);
}); });
it('authn fail, authFailure handles', async function () { it('authn fail, authFailure handles', async function () {
this.timeout(100);
handlers.authFailure.shouldHandle = true; handlers.authFailure.shouldHandle = true;
await agent.get('/').expect(200, 'authFailure'); await agent.get('/').expect(200, 'authFailure');
assert(handlers.authnFailure.called); assert(handlers.authnFailure.called);
@ -442,6 +484,7 @@ describe(__filename, function () {
assert(handlers.authFailure.called); assert(handlers.authFailure.called);
}); });
it('authnFailure trumps authFailure', async function () { it('authnFailure trumps authFailure', async function () {
this.timeout(100);
handlers.authnFailure.shouldHandle = true; handlers.authnFailure.shouldHandle = true;
handlers.authFailure.shouldHandle = true; handlers.authFailure.shouldHandle = true;
await agent.get('/').expect(200, 'authnFailure'); await agent.get('/').expect(200, 'authnFailure');
@ -451,12 +494,14 @@ describe(__filename, function () {
// authz failure tests // authz failure tests
it('authz fail, no hooks handle -> 403', async function () { it('authz fail, no hooks handle -> 403', async function () {
this.timeout(100);
await agent.get('/').auth('user', 'user-password').expect(403); await agent.get('/').auth('user', 'user-password').expect(403);
assert(!handlers.authnFailure.called); assert(!handlers.authnFailure.called);
assert(handlers.authzFailure.called); assert(handlers.authzFailure.called);
assert(handlers.authFailure.called); assert(handlers.authFailure.called);
}); });
it('authz fail, authzFailure handles', async function () { it('authz fail, authzFailure handles', async function () {
this.timeout(100);
handlers.authzFailure.shouldHandle = true; handlers.authzFailure.shouldHandle = true;
await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure'); await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure');
assert(!handlers.authnFailure.called); assert(!handlers.authnFailure.called);
@ -464,6 +509,7 @@ describe(__filename, function () {
assert(!handlers.authFailure.called); assert(!handlers.authFailure.called);
}); });
it('authz fail, authFailure handles', async function () { it('authz fail, authFailure handles', async function () {
this.timeout(100);
handlers.authFailure.shouldHandle = true; handlers.authFailure.shouldHandle = true;
await agent.get('/').auth('user', 'user-password').expect(200, 'authFailure'); await agent.get('/').auth('user', 'user-password').expect(200, 'authFailure');
assert(!handlers.authnFailure.called); assert(!handlers.authnFailure.called);
@ -471,6 +517,7 @@ describe(__filename, function () {
assert(handlers.authFailure.called); assert(handlers.authFailure.called);
}); });
it('authzFailure trumps authFailure', async function () { it('authzFailure trumps authFailure', async function () {
this.timeout(100);
handlers.authzFailure.shouldHandle = true; handlers.authzFailure.shouldHandle = true;
handlers.authFailure.shouldHandle = true; handlers.authFailure.shouldHandle = true;
await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure'); await agent.get('/').auth('user', 'user-password').expect(200, 'authzFailure');

View file

@ -10,6 +10,7 @@ describe('All the alphabet works n stuff', function () {
}); });
it('when you enter any char it appears right', function (done) { it('when you enter any char it appears right', function (done) {
this.timeout(250);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element out of the inner iframe // get the first text element out of the inner iframe

View file

@ -8,6 +8,7 @@ describe('bold button', function () {
}); });
it('makes text bold on click', function (done) { it('makes text bold on click', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -36,6 +37,7 @@ describe('bold button', function () {
}); });
it('makes text bold on keypress', function (done) { it('makes text bold on keypress', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element out of the inner iframe // get the first text element out of the inner iframe

View file

@ -9,7 +9,7 @@ describe('change user color', function () {
it('Color picker matches original color and remembers the user color' + it('Color picker matches original color and remembers the user color' +
' after a refresh', function (done) { ' after a refresh', function (done) {
this.timeout(60000); this.timeout(10000);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible // 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) { it('Own user color is shown when you enter a chat', function (done) {
this.timeout(1000);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
const $colorOption = helper.padChrome$('#options-colorscheck'); const $colorOption = helper.padChrome$('#options-colorscheck');

View file

@ -7,6 +7,7 @@ describe('change username value', function () {
}); });
it('Remembers the user name after a refresh', async function () { it('Remembers the user name after a refresh', async function () {
this.timeout(1500);
helper.toggleUserList(); helper.toggleUserList();
helper.setUserName('😃'); helper.setUserName('😃');
@ -21,6 +22,7 @@ describe('change username value', function () {
}); });
it('Own user name is shown when you enter a chat', async function () { it('Own user name is shown when you enter a chat', async function () {
this.timeout(1500);
helper.toggleUserList(); helper.toggleUserList();
helper.setUserName('😃'); helper.setUserName('😃');

View file

@ -8,6 +8,7 @@ describe('Chat messages and UI', function () {
it('opens chat, sends a message, makes sure it exists ' + it('opens chat, sends a message, makes sure it exists ' +
'on the page and hides chat', async function () { 'on the page and hides chat', async function () {
this.timeout(3000);
const chatValue = 'JohnMcLear'; const chatValue = 'JohnMcLear';
await helper.showChat(); await helper.showChat();
@ -50,6 +51,7 @@ describe('Chat messages and UI', function () {
it('makes chat stick to right side of the screen via settings, ' + it('makes chat stick to right side of the screen via settings, ' +
'remove sticky via settings, close it', async function () { 'remove sticky via settings, close it', async function () {
this.timeout(5000);
await helper.showSettings(); await helper.showSettings();
await helper.enableStickyChatviaSettings(); await helper.enableStickyChatviaSettings();
@ -67,6 +69,7 @@ describe('Chat messages and UI', function () {
it('makes chat stick to right side of the screen via icon on the top' + it('makes chat stick to right side of the screen via icon on the top' +
' right, remove sticky via icon, close it', async function () { ' right, remove sticky via icon, close it', async function () {
this.timeout(5000);
await helper.showChat(); await helper.showChat();
await helper.enableStickyChatviaIcon(); await helper.enableStickyChatviaIcon();
@ -111,6 +114,6 @@ describe('Chat messages and UI', function () {
}, 1000); }, 1000);
}, },
}); });
}, 1000); }, 3000);
}); });
}); });

View file

@ -30,6 +30,7 @@ describe('chat-load-messages', function () {
}); });
it('checks initial message count', function (done) { it('checks initial message count', function (done) {
this.timeout(1000);
let chatText; let chatText;
const expectedCount = 101; const expectedCount = 101;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -45,6 +46,7 @@ describe('chat-load-messages', function () {
}); });
it('loads more messages', function (done) { it('loads more messages', function (done) {
this.timeout(3000);
const expectedCount = 122; const expectedCount = 122;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
const chatButton = chrome$('#chaticon'); const chatButton = chrome$('#chaticon');
@ -60,6 +62,7 @@ describe('chat-load-messages', function () {
}); });
it('checks for button vanishing', function (done) { it('checks for button vanishing', function (done) {
this.timeout(2000);
const expectedDisplay = 'none'; const expectedDisplay = 'none';
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
const chatButton = chrome$('#chaticon'); const chatButton = chrome$('#chaticon');

View file

@ -8,6 +8,7 @@ describe('clear authorship colors button', function () {
}); });
it('makes text clear authorship colors', function (done) { it('makes text clear authorship colors', function (done) {
this.timeout(2500);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -55,6 +56,7 @@ describe('clear authorship colors button', function () {
}); });
it("makes text clear authorship colors and checks it can't be undone", function (done) { it("makes text clear authorship colors and checks it can't be undone", function (done) {
this.timeout(1500);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -8,6 +8,7 @@ describe('delete keystroke', function () {
}); });
it('makes text delete', function (done) { it('makes text delete', function (done) {
this.timeout(50);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element out of the inner iframe // get the first text element out of the inner iframe

View file

@ -31,6 +31,7 @@ describe('drag and drop', function () {
}); });
it('moves text back to its original place', function (done) { it('moves text back to its original place', function (done) {
this.timeout(50);
// test text was removed from drop target // test text was removed from drop target
const $targetLine = getLine(TARGET_LINE); const $targetLine = getLine(TARGET_LINE);
expect($targetLine.text()).to.be('Target line []'); expect($targetLine.text()).to.be('Target line []');
@ -68,6 +69,7 @@ describe('drag and drop', function () {
}); });
it('moves text back to its original place', function (done) { it('moves text back to its original place', function (done) {
this.timeout(50);
// test text was removed from drop target // test text was removed from drop target
const $targetLine = getLine(TARGET_LINE); const $targetLine = getLine(TARGET_LINE);
expect($targetLine.text()).to.be('Target line []'); expect($targetLine.text()).to.be('Target line []');

View file

@ -57,6 +57,7 @@ describe('embed links', function () {
describe('the share link', function () { describe('the share link', function () {
it('is the actual pad url', function (done) { it('is the actual pad url', function (done) {
this.timeout(50);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// open share dropdown // open share dropdown
@ -73,6 +74,7 @@ describe('embed links', function () {
describe('the embed as iframe code', function () { describe('the embed as iframe code', function () {
it('is an iframe with the the correct url parameters and correct size', function (done) { it('is an iframe with the the correct url parameters and correct size', function (done) {
this.timeout(50);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// open share dropdown // open share dropdown
@ -96,6 +98,7 @@ describe('embed links', function () {
describe('the share link', function () { describe('the share link', function () {
it('shows a read only url', function (done) { it('shows a read only url', function (done) {
this.timeout(50);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// open share dropdown // open share dropdown
@ -114,6 +117,7 @@ describe('embed links', function () {
describe('the embed as iframe code', function () { describe('the embed as iframe code', function () {
it('is an iframe with the the correct url parameters and correct size', function (done) { it('is an iframe with the the correct url parameters and correct size', function (done) {
this.timeout(50);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// open share dropdown // open share dropdown

View file

@ -7,6 +7,7 @@ describe('enter keystroke', function () {
this.timeout(60000); this.timeout(60000);
}); });
it('creates a new line & puts cursor onto a new line', function (done) { it('creates a new line & puts cursor onto a new line', function (done) {
this.timeout(2000);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element out of the inner iframe // get the first text element out of the inner iframe

View file

@ -8,6 +8,7 @@ describe('font select', function () {
}); });
it('makes text RobotoMono', function (done) { it('makes text RobotoMono', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -8,6 +8,7 @@ describe('indentation button', function () {
}); });
it('indent text with keypress', function (done) { it('indent text with keypress', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element out of the inner iframe // 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) { it('indent text with button', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -34,6 +36,7 @@ describe('indentation button', function () {
}); });
it('keeps the indent on enter for the new line', function (done) { it('keeps the indent on enter for the new line', function (done) {
this.timeout(1200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -59,6 +62,7 @@ describe('indentation button', function () {
it('indents text with spaces on enter if previous line ends ' + it('indents text with spaces on enter if previous line ends ' +
"with ':', '[', '(', or '{'", function (done) { "with ':', '[', '(', or '{'", function (done) {
this.timeout(1200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// type a bit, make a line break and type again // 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 ' + it('appends indentation to the indent of previous line if previous line ends ' +
"with ':', '[', '(', or '{'", function (done) { "with ':', '[', '(', or '{'", function (done) {
this.timeout(1200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// type a bit, make a line break and type again // 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 " + it("issue #2772 shows '*' when multiple indented lines " +
' receive a style and are outdented', async function () { ' receive a style and are outdented', async function () {
this.timeout(1200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -8,6 +8,7 @@ describe('italic some text', function () {
}); });
it('makes text italic using button', function (done) { it('makes text italic using button', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -37,6 +38,7 @@ describe('italic some text', function () {
}); });
it('makes text italic using keypress', function (done) { it('makes text italic using keypress', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element out of the inner iframe // get the first text element out of the inner iframe

View file

@ -16,6 +16,7 @@ describe('Language select and change', function () {
// Destroy language cookies // Destroy language cookies
it('makes text german', function (done) { it('makes text german', function (done) {
this.timeout(1000);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible // 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) { it('makes text English', function (done) {
this.timeout(1000);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible // 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) { it('changes direction when picking an rtl lang', function (done) {
this.timeout(1000);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible // click on the settings button to make settings visible

View file

@ -27,6 +27,7 @@ describe('author of pad edition', function () {
// author 2 makes some changes on the pad // author 2 makes some changes on the pad
it('Clears Authorship by second user', function (done) { it('Clears Authorship by second user', function (done) {
this.timeout(100);
clearAuthorship(done); clearAuthorship(done);
}); });

View file

@ -9,6 +9,7 @@ describe('ordered_list.js', function () {
}); });
it('inserts ordered list text', function (done) { it('inserts ordered list text', function (done) {
this.timeout(200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -28,6 +29,7 @@ describe('ordered_list.js', function () {
}); });
it('inserts unordered list', function (done) { it('inserts unordered list', function (done) {
this.timeout(50);
helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1) helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1)
.done(done); .done(done);
}); });
@ -52,6 +54,7 @@ describe('ordered_list.js', function () {
}); });
it('does not insert unordered list', function (done) { it('does not insert unordered list', function (done) {
this.timeout(3000);
helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1) helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1)
.done(() => { .done(() => {
expect().fail(() => 'Unordered list inserted, should ignore shortcut'); expect().fail(() => 'Unordered list inserted, should ignore shortcut');
@ -73,6 +76,7 @@ describe('ordered_list.js', function () {
}); });
it('inserts unordered list', function (done) { it('inserts unordered list', function (done) {
this.timeout(200);
helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1) helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1)
.done(done); .done(done);
}); });
@ -97,6 +101,7 @@ describe('ordered_list.js', function () {
}); });
it('does not insert unordered list', function (done) { it('does not insert unordered list', function (done) {
this.timeout(3000);
helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1) helper.waitFor(() => helper.padInner$('div').first().find('ol li').length === 1)
.done(() => { .done(() => {
expect().fail(() => 'Unordered list inserted, should ignore shortcut'); expect().fail(() => 'Unordered list inserted, should ignore shortcut');
@ -175,6 +180,7 @@ describe('ordered_list.js', function () {
}); });
it('indent and de-indent list item with keypress', function (done) { it('indent and de-indent list item with keypress', function (done) {
this.timeout(200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -210,6 +216,7 @@ describe('ordered_list.js', function () {
}); });
it('indent and de-indent list item with indent button', function (done) { it('indent and de-indent list item with indent button', function (done) {
this.timeout(1000);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -18,6 +18,7 @@ describe('Pad modal', function () {
}); });
it('disables editor', function (done) { it('disables editor', function (done) {
this.timeout(200);
expect(isEditorDisabled()).to.be(true); expect(isEditorDisabled()).to.be(true);
done(); done();
@ -25,6 +26,7 @@ describe('Pad modal', function () {
context('and user clicks on editor', function () { context('and user clicks on editor', function () {
it('does not close the modal', function (done) { it('does not close the modal', function (done) {
this.timeout(200);
clickOnPadInner(); clickOnPadInner();
const $modal = helper.padChrome$(MODAL_SELECTOR); const $modal = helper.padChrome$(MODAL_SELECTOR);
const modalIsVisible = $modal.hasClass('popup-show'); const modalIsVisible = $modal.hasClass('popup-show');
@ -37,6 +39,7 @@ describe('Pad modal', function () {
context('and user clicks on pad outer', function () { context('and user clicks on pad outer', function () {
it('does not close the modal', function (done) { it('does not close the modal', function (done) {
this.timeout(200);
clickOnPadOuter(); clickOnPadOuter();
const $modal = helper.padChrome$(MODAL_SELECTOR); const $modal = helper.padChrome$(MODAL_SELECTOR);
const modalIsVisible = $modal.hasClass('popup-show'); const modalIsVisible = $modal.hasClass('popup-show');
@ -68,6 +71,7 @@ describe('Pad modal', function () {
*/ */
context('and user clicks on editor', function () { context('and user clicks on editor', function () {
it('closes the modal', async function () { it('closes the modal', async function () {
this.timeout(200);
clickOnPadInner(); clickOnPadInner();
await helper.waitForPromise(() => isModalOpened(MODAL_SELECTOR) === false); await helper.waitForPromise(() => isModalOpened(MODAL_SELECTOR) === false);
}); });
@ -75,6 +79,7 @@ describe('Pad modal', function () {
context('and user clicks on pad outer', function () { context('and user clicks on pad outer', function () {
it('closes the modal', async function () { it('closes the modal', async function () {
this.timeout(200);
clickOnPadOuter(); clickOnPadOuter();
await helper.waitForPromise(() => isModalOpened(MODAL_SELECTOR) === false); await helper.waitForPromise(() => isModalOpened(MODAL_SELECTOR) === false);
}); });

View file

@ -7,6 +7,7 @@ describe('undo button then redo button', function () {
}); });
it('redo some typing with button', function (done) { it('redo some typing with button', function (done) {
this.timeout(200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -34,6 +35,7 @@ describe('undo button then redo button', function () {
}); });
it('redo some typing with keypress', function (done) { it('redo some typing with keypress', function (done) {
this.timeout(200);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element inside the editable space // get the first text element inside the editable space

View file

@ -12,7 +12,7 @@ describe('scrollTo.js', function () {
}); });
it('Scrolls down to Line 4', async function () { it('Scrolls down to Line 4', async function () {
this.timeout(10000); this.timeout(100);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
await helper.waitForPromise(() => { await helper.waitForPromise(() => {
const topOffset = parseInt(chrome$('iframe').first('iframe') const topOffset = parseInt(chrome$('iframe').first('iframe')
@ -33,7 +33,7 @@ describe('scrollTo.js', function () {
}); });
it('Does NOT change scroll', async function () { it('Does NOT change scroll', async function () {
this.timeout(10000); this.timeout(100);
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
await helper.waitForPromise(() => { await helper.waitForPromise(() => {
const topOffset = parseInt(chrome$('iframe').first('iframe') const topOffset = parseInt(chrome$('iframe').first('iframe')

View file

@ -44,12 +44,14 @@ describe('select formatting buttons when selection has style applied', function
const testIfFormattingButtonIsDeselected = function (style) { const testIfFormattingButtonIsDeselected = function (style) {
it(`deselects the ${style} button`, function (done) { it(`deselects the ${style} button`, function (done) {
this.timeout(50);
helper.waitFor(() => isButtonSelected(style) === false).done(done); helper.waitFor(() => isButtonSelected(style) === false).done(done);
}); });
}; };
const testIfFormattingButtonIsSelected = function (style) { const testIfFormattingButtonIsSelected = function (style) {
it(`selects the ${style} button`, function (done) { it(`selects the ${style} button`, function (done) {
this.timeout(50);
helper.waitFor(() => isButtonSelected(style)).done(done); helper.waitFor(() => isButtonSelected(style)).done(done);
}); });
}; };
@ -129,6 +131,7 @@ describe('select formatting buttons when selection has style applied', function
context('when user applies a style and the selection does not change', function () { context('when user applies a style and the selection does not change', function () {
it('selects the style button', async function () { it('selects the style button', async function () {
this.timeout(50);
const style = STYLES[0]; // italic const style = STYLES[0]; // italic
applyStyleOnLine(style, FIRST_LINE); applyStyleOnLine(style, FIRST_LINE);
await helper.waitForPromise(() => isButtonSelected(style) === true); await helper.waitForPromise(() => isButtonSelected(style) === true);

View file

@ -8,6 +8,7 @@ describe('strikethrough button', function () {
}); });
it('makes text strikethrough', function (done) { it('makes text strikethrough', function (done) {
this.timeout(100);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -9,6 +9,7 @@ describe('timeslider follow', function () {
// TODO needs test if content is also followed, when user a makes edits // TODO needs test if content is also followed, when user a makes edits
// while user b is in the timeslider // while user b is in the timeslider
it("content as it's added to timeslider", async function () { it("content as it's added to timeslider", async function () {
this.timeout(10000);
// send 6 revisions // send 6 revisions
const revs = 6; const revs = 6;
const message = 'a\n\n\n\n\n\n\n\n\n\n'; const message = 'a\n\n\n\n\n\n\n\n\n\n';

View file

@ -10,6 +10,7 @@ describe('timeslider', function () {
* @todo test authorsList * @todo test authorsList
*/ */
it("Shows a date/time in the timeslider and make sure it doesn't include NaN", async function () { it("Shows a date/time in the timeslider and make sure it doesn't include NaN", async function () {
this.timeout(12000);
// make some changes to produce 3 revisions // make some changes to produce 3 revisions
const revs = 3; const revs = 3;

View file

@ -9,6 +9,7 @@ describe('timeslider', function () {
}); });
it('Makes sure the export URIs are as expected when the padID is numeric', async function () { it('Makes sure the export URIs are as expected when the padID is numeric', async function () {
this.timeout(60000);
await helper.edit('a\n'); await helper.edit('a\n');
await helper.gotoTimeslider(1); await helper.gotoTimeslider(1);

View file

@ -8,6 +8,7 @@ describe('timeslider', function () {
}); });
it('loads adds a hundred revisions', function (done) { // passes it('loads adds a hundred revisions', function (done) { // passes
this.timeout(100000);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -7,6 +7,8 @@ describe('undo button', function () {
}); });
it('undo some typing by clicking undo button', function (done) { it('undo some typing by clicking undo button', function (done) {
this.timeout(100);
this.timeout(150);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -31,6 +33,7 @@ describe('undo button', function () {
}); });
it('undo some typing using a keypress', function (done) { it('undo some typing using a keypress', function (done) {
this.timeout(150);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
// get the first text element inside the editable space // get the first text element inside the editable space

View file

@ -9,6 +9,7 @@ describe('unordered_list.js', function () {
}); });
it('insert unordered list text then removes by outdent', function (done) { it('insert unordered list text then removes by outdent', function (done) {
this.timeout(150);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
const originalText = inner$('div').first().text(); const originalText = inner$('div').first().text();
@ -42,6 +43,7 @@ describe('unordered_list.js', function () {
}); });
it('insert unordered list text then remove by clicking list again', function (done) { it('insert unordered list text then remove by clicking list again', function (done) {
this.timeout(150);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
const originalText = inner$('div').first().text(); const originalText = inner$('div').first().text();
@ -77,6 +79,7 @@ describe('unordered_list.js', function () {
}); });
it('Keeps the unordered list on enter for the new line', function (done) { it('Keeps the unordered list on enter for the new line', function (done) {
this.timeout(250);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -108,6 +111,7 @@ describe('unordered_list.js', function () {
}); });
it('indent and de-indent list item with keypress', function (done) { it('indent and de-indent list item with keypress', function (done) {
this.timeout(150);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;
@ -142,6 +146,7 @@ describe('unordered_list.js', function () {
}); });
it('indent and de-indent list item with indent button', function (done) { it('indent and de-indent list item with indent button', function (done) {
this.timeout(150);
const inner$ = helper.padInner$; const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$; const chrome$ = helper.padChrome$;

View file

@ -20,6 +20,7 @@ describe('urls', function () {
describe('entering a URL makes a link', function () { describe('entering a URL makes a link', function () {
for (const url of ['https://etherpad.org', 'www.etherpad.org']) { for (const url of ['https://etherpad.org', 'www.etherpad.org']) {
it(url, async function () { it(url, async function () {
this.timeout(5000);
const url = 'https://etherpad.org'; const url = 'https://etherpad.org';
await helper.edit(url); await helper.edit(url);
await helper.waitForPromise(() => txt().find('a').length === 1, 2000); await helper.waitForPromise(() => txt().find('a').length === 1, 2000);