diff --git a/tests/backend/specs/api/api.js b/tests/backend/specs/api/api.js index e5fca6bca..a3d29fd4f 100644 --- a/tests/backend/specs/api/api.js +++ b/tests/backend/specs/api/api.js @@ -18,44 +18,46 @@ var apiVersion = 1; var testPadId = makeid(); -describe('API Versioning', function() { - it('errors if can not connect', function(done) { - api - .get('/api/') - .expect(function(res) { - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error('No version set in API'); - return; - }) - .expect(200, done); +describe(__filename, function() { + describe('API Versioning', function() { + it('errors if can not connect', function(done) { + api + .get('/api/') + .expect(function(res) { + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error('No version set in API'); + return; + }) + .expect(200, done); + }); }); -}); -describe('OpenAPI definition', function() { - it('generates valid openapi definition document', function(done) { - api - .get('/api/openapi.json') - .expect(function(res) { - const { valid, errors } = validateOpenAPI(res.body, 3); - if (!valid) { - const prettyErrors = JSON.stringify(errors, null, 2); - throw new Error(`Document is not valid OpenAPI. ${errors.length} validation errors:\n${prettyErrors}`); - } - return; - }) - .expect(200, done); + describe('OpenAPI definition', function() { + it('generates valid openapi definition document', function(done) { + api + .get('/api/openapi.json') + .expect(function(res) { + const { valid, errors } = validateOpenAPI(res.body, 3); + if (!valid) { + const prettyErrors = JSON.stringify(errors, null, 2); + throw new Error(`Document is not valid OpenAPI. ${errors.length} validation errors:\n${prettyErrors}`); + } + return; + }) + .expect(200, done); + }); }); -}); -describe('jsonp support', function() { - it('supports jsonp calls', function(done) { - api - .get(endPoint('createPad') + '&jsonp=jsonp_1&padID=' + testPadId) - .expect(function(res) { - if (!res.text.match('jsonp_1')) throw new Error('no jsonp call seen'); - }) - .expect('Content-Type', /javascript/) - .expect(200, done); + describe('jsonp support', function() { + it('supports jsonp calls', function(done) { + api + .get(endPoint('createPad') + '&jsonp=jsonp_1&padID=' + testPadId) + .expect(function(res) { + if (!res.text.match('jsonp_1')) throw new Error('no jsonp call seen'); + }) + .expect('Content-Type', /javascript/) + .expect(200, done); + }); }); }); diff --git a/tests/backend/specs/api/characterEncoding.js b/tests/backend/specs/api/characterEncoding.js index ed192d325..494a1bbd6 100644 --- a/tests/backend/specs/api/characterEncoding.js +++ b/tests/backend/specs/api/characterEncoding.js @@ -14,76 +14,78 @@ const apiKey = common.apiKey; var apiVersion = 1; var testPadId = makeid(); -describe('Connectivity For Character Encoding', function(){ - it('can connect', function(done) { - api.get('/api/') - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('API Versioning', function(){ - it('finds the version tag', function(done) { - api.get('/api/') - .expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .expect(200, done) - }); -}) - -describe('Permission', function(){ - it('errors with invalid APIKey', function(done) { - // 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 - var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; - api.get(permErrorURL) - .expect(401, done) - }); -}) - -describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setHTML', function(){ - it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function(done) { - fs.readFile('../tests/backend/specs/api/emojis.html', 'utf8', function(err, html) { - api.post(endPoint('setHTML')) - .send({ - "padID": testPadId, - "html": html, - }) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Can't set HTML properly"); - }) - .expect('Content-Type', /json/) - .expect(200, done); +describe(__filename, function() { + describe('Connectivity For Character Encoding', function() { + it('can connect', function(done) { + api.get('/api/') + .expect('Content-Type', /json/) + .expect(200, done) }); - }); -}) + }) -describe('getHTML', function(){ - it('get the HTML of Pad with emojis', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - if (res.body.data.html.indexOf("🇼") === -1) { - throw new Error("Unable to get the HTML"); - } - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) + describe('API Versioning', function() { + it('finds the version tag', function(done) { + api.get('/api/') + .expect(function(res){ + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error("No version set in API"); + return; + }) + .expect(200, done) + }); + }) + + describe('Permission', function() { + it('errors with invalid APIKey', function(done) { + // 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 + var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; + api.get(permErrorURL) + .expect(401, done) + }); + }) + + describe('createPad', function() { + it('creates a new Pad', function(done) { + api.get(endPoint('createPad')+"&padID="+testPadId) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) + + describe('setHTML', function() { + it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function(done) { + fs.readFile('../tests/backend/specs/api/emojis.html', 'utf8', function(err, html) { + api.post(endPoint('setHTML')) + .send({ + "padID": testPadId, + "html": html, + }) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Can't set HTML properly"); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); + }) + + describe('getHTML', function() { + it('get the HTML of Pad with emojis', function(done) { + api.get(endPoint('getHTML')+"&padID="+testPadId) + .expect(function(res){ + if (res.body.data.html.indexOf("🇼") === -1) { + throw new Error("Unable to get the HTML"); + } + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) +}); /* diff --git a/tests/backend/specs/api/chat.js b/tests/backend/specs/api/chat.js index 293b4a145..a7c6c0762 100644 --- a/tests/backend/specs/api/chat.js +++ b/tests/backend/specs/api/chat.js @@ -11,89 +11,91 @@ var authorID = ""; var padID = makeid(); var timestamp = Date.now(); -describe('API Versioning', function(){ - it('errors if can not connect', function(done) { - api.get('/api/') - .expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .expect(200, done) - }); -}) +describe(__filename, function() { + describe('API Versioning', function(){ + it('errors if can not connect', function(done) { + api.get('/api/') + .expect(function(res){ + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error("No version set in API"); + return; + }) + .expect(200, done) + }); + }) -// BEGIN GROUP AND AUTHOR TESTS -///////////////////////////////////// -///////////////////////////////////// + // BEGIN GROUP AND AUTHOR TESTS + ///////////////////////////////////// + ///////////////////////////////////// -/* Tests performed --> createPad(padID) - -> createAuthor([name]) -- should return an authorID - -> appendChatMessage(padID, text, authorID, time) - -> getChatHead(padID) - -> getChatHistory(padID) -*/ + /* Tests performed + -> createPad(padID) + -> createAuthor([name]) -- should return an authorID + -> appendChatMessage(padID, text, authorID, time) + -> getChatHead(padID) + -> getChatHistory(padID) + */ -describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) + describe('createPad', function(){ + it('creates a new Pad', function(done) { + api.get(endPoint('createPad')+"&padID="+padID) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) -describe('createAuthor', function(){ - it('Creates an author with a name set', function(done) { - api.get(endPoint('createAuthor')) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create author"); - authorID = res.body.data.authorID; // we will be this author for the rest of the tests - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) + describe('createAuthor', function(){ + it('Creates an author with a name set', function(done) { + api.get(endPoint('createAuthor')) + .expect(function(res){ + if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create author"); + authorID = res.body.data.authorID; // we will be this author for the rest of the tests + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) -describe('appendChatMessage', function(){ - it('Adds a chat message to the pad', function(done) { - api.get(endPoint('appendChatMessage')+"&padID="+padID+"&text=blalblalbha&authorID="+authorID+"&time="+timestamp) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create chat message"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) + describe('appendChatMessage', function(){ + it('Adds a chat message to the pad', function(done) { + api.get(endPoint('appendChatMessage')+"&padID="+padID+"&text=blalblalbha&authorID="+authorID+"&time="+timestamp) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Unable to create chat message"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) -describe('getChatHead', function(){ - it('Gets the head of chat', function(done) { - api.get(endPoint('getChatHead')+"&padID="+padID) - .expect(function(res){ - if(res.body.data.chatHead !== 0) throw new Error("Chat Head Length is wrong"); + describe('getChatHead', function(){ + it('Gets the head of chat', function(done) { + api.get(endPoint('getChatHead')+"&padID="+padID) + .expect(function(res){ + if(res.body.data.chatHead !== 0) throw new Error("Chat Head Length is wrong"); - if(res.body.code !== 0) throw new Error("Unable to get chat head"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) + if(res.body.code !== 0) throw new Error("Unable to get chat head"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) -describe('getChatHistory', function(){ - it('Gets Chat History of a Pad', function(done) { - api.get(endPoint('getChatHistory')+"&padID="+padID) - .expect(function(res){ - if(res.body.data.messages.length !== 1) throw new Error("Chat History Length is wrong"); - if(res.body.code !== 0) throw new Error("Unable to get chat history"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) + describe('getChatHistory', function(){ + it('Gets Chat History of a Pad', function(done) { + api.get(endPoint('getChatHistory')+"&padID="+padID) + .expect(function(res){ + if(res.body.data.messages.length !== 1) throw new Error("Chat History Length is wrong"); + if(res.body.code !== 0) throw new Error("Unable to get chat history"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) +}); var endPoint = function(point){ return '/api/'+apiVersion+'/'+point+'?apikey='+apiKey; diff --git a/tests/backend/specs/api/importexport.js b/tests/backend/specs/api/importexport.js index 67ced55db..3744dd67d 100644 --- a/tests/backend/specs/api/importexport.js +++ b/tests/backend/specs/api/importexport.js @@ -56,38 +56,39 @@ var testImports = { */ } -Object.keys(testImports).forEach(function (testName) { - var testPadId = makeid(); - test = testImports[testName]; - describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) +describe(__filename, function() { + Object.keys(testImports).forEach(function(testName) { + var testPadId = makeid(); + test = testImports[testName]; + describe('createPad', function() { + it('creates a new Pad', function(done) { + api.get(endPoint('createPad') + "&padID=" + testPadId) + .expect(function(res) { + if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) - describe('setHTML', function(){ - it('Sets the HTML', function(done) { - api.get(endPoint('setHTML')+"&padID="+testPadId+"&html="+test.input) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Error:"+testName) - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) + describe('setHTML', function() { + it('Sets the HTML', function(done) { + api.get(endPoint('setHTML') + "&padID=" + testPadId + "&html=" + test.input) + .expect(function(res) { + if(res.body.code !== 0) throw new Error("Error:" + testName) + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) - describe('getHTML', function(){ - it('Gets back the HTML of a Pad', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - var receivedHtml = res.body.data.html; - if (receivedHtml !== test.expectedHTML) { - throw new Error(`HTML received from export is not the one we were expecting. + describe('getHTML', function() { + it('Gets back the HTML of a Pad', function(done) { + api.get(endPoint('getHTML') + "&padID=" + testPadId) + .expect(function(res) { + var receivedHtml = res.body.data.html; + if (receivedHtml !== test.expectedHTML) { + throw new Error(`HTML received from export is not the one we were expecting. Test Name: ${testName} @@ -99,20 +100,20 @@ Object.keys(testImports).forEach(function (testName) { Which is a different version of the originally imported one: ${test.input}`); - } - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) + } + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) - describe('getText', function(){ - it('Gets back the Text of a Pad', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - var receivedText = res.body.data.text; - if (receivedText !== test.expectedText) { - throw new Error(`Text received from export is not the one we were expecting. + describe('getText', function() { + it('Gets back the Text of a Pad', function(done) { + api.get(endPoint('getText') + "&padID=" + testPadId) + .expect(function(res) { + var receivedText = res.body.data.text; + if (receivedText !== test.expectedText) { + throw new Error(`Text received from export is not the one we were expecting. Test Name: ${testName} @@ -124,12 +125,13 @@ Object.keys(testImports).forEach(function (testName) { Which is a different version of the originally imported one: ${test.input}`); - } - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); - }) + } + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); + }) + }); }); diff --git a/tests/backend/specs/api/importexportGetPost.js b/tests/backend/specs/api/importexportGetPost.js index edc51f92d..1775d2ed7 100644 --- a/tests/backend/specs/api/importexportGetPost.js +++ b/tests/backend/specs/api/importexportGetPost.js @@ -23,326 +23,327 @@ var apiVersion = 1; const testPadId = makeid(); const testPadIdEnc = encodeURIComponent(testPadId); -before(async function() { agent = await common.init(); }); +describe(__filename, function() { + before(async function() { agent = await common.init(); }); -describe('Connectivity', function(){ - it('can connect', async function() { - await agent.get('/api/') - .expect(200) - .expect('Content-Type', /json/); - }); -}) - -describe('API Versioning', function(){ - it('finds the version tag', async function() { - await agent.get('/api/') - .expect(200) - .expect((res) => assert(res.body.currentVersion)); - }); -}) - -/* -Tests ------ - -Test. - / Create a pad - / Set pad contents - / Try export pad in various formats - / Get pad contents and ensure it matches imported contents - -Test. - / Try to export a pad that doesn't exist // Expect failure - -Test. - / Try to import an unsupported file to a pad that exists - --- TODO: Test. - Try to import to a file and abort it half way through - -Test. - Try to import to files of varying size. - -Example Curl command for testing import URI: - curl -s -v --form file=@/home/jose/test.txt http://127.0.0.1:9001/p/foo/import -*/ - -describe('Imports and Exports', function(){ - const backups = {}; - - beforeEach(async function() { - // Note: This is a shallow copy. - backups.settings = Object.assign({}, settings); - }); - - afterEach(async function() { - // Note: This does not unset settings that were added. - Object.assign(settings, backups.settings); - }); - - it('creates a new Pad, imports content to it, checks that content', async function() { - await agent.get(endPoint('createPad') + `&padID=${testPadId}`) - .expect(200) - .expect('Content-Type', /json/) - .expect((res) => assert.equal(res.body.code, 0)); - await agent.post(`/p/${testPadId}/import`) - .attach('file', padText, {filename: '/test.txt', contentType: 'text/plain'}) - .expect(200); - await agent.get(endPoint('getText') + `&padID=${testPadId}`) - .expect(200) - .expect((res) => assert.equal(res.body.data.text, padText.toString())); - }); - - it('gets read only pad Id and exports the html and text for this pad', async function(){ - let ro = await agent.get(endPoint('getReadOnlyID')+"&padID="+testPadId) - .expect(200) - .expect((res) => assert.ok(JSON.parse(res.text).data.readOnlyID)); - let readOnlyId = JSON.parse(ro.text).data.readOnlyID; - - await agent.get(`/p/${readOnlyId}/export/html`) - .expect(200) - .expect((res) => assert(res.text.indexOf("This is the") !== -1)); - - await agent.get(`/p/${readOnlyId}/export/txt`) - .expect(200) - .expect((res) => assert(res.text.indexOf("This is the") !== -1)); - }); - - - describe('Import/Export tests requiring AbiWord/LibreOffice', function() { - before(function() { - if ((!settings.abiword || settings.abiword.indexOf('/') === -1) && - (!settings.soffice || settings.soffice.indexOf('/') === -1)) { - this.skip(); - } - }); - - // For some reason word import does not work in testing.. - // TODO: fix support for .doc files.. - it('Tries to import .doc that uses soffice or abiword', async function() { - await agent.post(`/p/${testPadId}/import`) - .attach('file', wordDoc, {filename: '/test.doc', contentType: 'application/msword'}) + describe('Connectivity', function(){ + it('can connect', async function() { + await agent.get('/api/') .expect(200) - .expect(/FrameCall\('undefined', 'ok'\);/); + .expect('Content-Type', /json/); }); + }) - it('exports DOC', async function() { - await agent.get(`/p/${testPadId}/export/doc`) - .buffer(true).parse(superagent.parse['application/octet-stream']) + describe('API Versioning', function(){ + it('finds the version tag', async function() { + await agent.get('/api/') .expect(200) - .expect((res) => assert(res.body.length >= 9000)); + .expect((res) => assert(res.body.currentVersion)); }); + }) - it('Tries to import .docx that uses soffice or abiword', async function() { - await agent.post(`/p/${testPadId}/import`) - .attach('file', wordXDoc, { - filename: '/test.docx', - contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - }) - .expect(200) - .expect(/FrameCall\('undefined', 'ok'\);/); - }); + /* + Tests + ----- - it('exports DOC from imported DOCX', async function() { - await agent.get(`/p/${testPadId}/export/doc`) - .buffer(true).parse(superagent.parse['application/octet-stream']) - .expect(200) - .expect((res) => assert(res.body.length >= 9100)); - }); + Test. + / Create a pad + / Set pad contents + / Try export pad in various formats + / Get pad contents and ensure it matches imported contents - it('Tries to import .pdf that uses soffice or abiword', async function() { - await agent.post(`/p/${testPadId}/import`) - .attach('file', pdfDoc, {filename: '/test.pdf', contentType: 'application/pdf'}) - .expect(200) - .expect(/FrameCall\('undefined', 'ok'\);/); - }); + Test. + / Try to export a pad that doesn't exist // Expect failure - it('exports PDF', async function() { - await agent.get(`/p/${testPadId}/export/pdf`) - .buffer(true).parse(superagent.parse['application/octet-stream']) - .expect(200) - .expect((res) => assert(res.body.length >= 1000)); - }); + Test. + / Try to import an unsupported file to a pad that exists - it('Tries to import .odt that uses soffice or abiword', async function() { - await agent.post(`/p/${testPadId}/import`) - .attach('file', odtDoc, {filename: '/test.odt', contentType: 'application/odt'}) - .expect(200) - .expect(/FrameCall\('undefined', 'ok'\);/); - }); + -- TODO: Test. + Try to import to a file and abort it half way through - it('exports ODT', async function() { - await agent.get(`/p/${testPadId}/export/odt`) - .buffer(true).parse(superagent.parse['application/octet-stream']) - .expect(200) - .expect((res) => assert(res.body.length >= 7000)); - }); + Test. + Try to import to files of varying size. - }); // End of AbiWord/LibreOffice tests. + Example Curl command for testing import URI: + curl -s -v --form file=@/home/jose/test.txt http://127.0.0.1:9001/p/foo/import + */ - it('Tries to import .etherpad', async function() { - await agent.post(`/p/${testPadId}/import`) - .attach('file', etherpadDoc, { - filename: '/test.etherpad', - contentType: 'application/etherpad', - }) - .expect(200) - .expect(/FrameCall\('true', 'ok'\);/); - }); - - it('exports Etherpad', async function() { - await agent.get(`/p/${testPadId}/export/etherpad`) - .buffer(true).parse(superagent.parse.text) - .expect(200) - .expect(/hello/); - }); - - it('exports HTML for this Etherpad file', async function() { - await agent.get(`/p/${testPadId}/export/html`) - .expect(200) - .expect('content-type', 'text/html; charset=utf-8') - .expect(/