From 3e5a9cdb97e9ec0a6a277a1274b280e062ab1ecc Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Mon, 23 Sep 2019 23:23:10 +0100 Subject: [PATCH] Tests: Make all tests use asyncTest for better error handling --- .travis.yml | 2 +- CliClient/tests/ArrayUtils.js | 20 ++-- CliClient/tests/StringUtils.js | 9 +- CliClient/tests/encryption.js | 44 +++------ CliClient/tests/htmlUtils.js | 27 ++--- CliClient/tests/markdownUtils.js | 15 +-- CliClient/tests/models_BaseItem.js | 8 -- CliClient/tests/services_rest_Api.js | 142 +++++++++------------------ 8 files changed, 87 insertions(+), 180 deletions(-) diff --git a/.travis.yml b/.travis.yml index 42e66ec5b..2ca355904 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ before_install: script: - | - # Instal tools + # Install tools cd Tools npm install diff --git a/CliClient/tests/ArrayUtils.js b/CliClient/tests/ArrayUtils.js index a77056e4d..ab8b891d0 100644 --- a/CliClient/tests/ArrayUtils.js +++ b/CliClient/tests/ArrayUtils.js @@ -3,7 +3,7 @@ require('app-module-path').addPath(__dirname); const { time } = require('lib/time-utils.js'); -const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); const ArrayUtils = require('lib/ArrayUtils.js'); process.on('unhandledRejection', (reason, p) => { @@ -16,7 +16,7 @@ describe('ArrayUtils', function() { done(); }); - it('should remove array elements', async (done) => { + it('should remove array elements', asyncTest(async () => { let a = ['un', 'deux', 'trois']; a = ArrayUtils.removeElement(a, 'deux'); @@ -27,11 +27,9 @@ describe('ArrayUtils', function() { a = ['un', 'deux', 'trois']; a = ArrayUtils.removeElement(a, 'not in there'); expect(a.length).toBe(3); + })); - done(); - }); - - it('should find items using binary search', async (done) => { + it('should find items using binary search', asyncTest(async () => { let items = ['aaa', 'ccc', 'bbb']; expect(ArrayUtils.binarySearch(items, 'bbb')).toBe(-1); // Array not sorted! items.sort(); @@ -42,17 +40,13 @@ describe('ArrayUtils', function() { items = []; expect(ArrayUtils.binarySearch(items, 'aaa')).toBe(-1); + })); - done(); - }); - - it('should compare arrays', async (done) => { + it('should compare arrays', asyncTest(async () => { expect(ArrayUtils.contentEquals([], [])).toBe(true); expect(ArrayUtils.contentEquals(['a'], ['a'])).toBe(true); expect(ArrayUtils.contentEquals(['b', 'a'], ['a', 'b'])).toBe(true); expect(ArrayUtils.contentEquals(['b'], ['a', 'b'])).toBe(false); - - done(); - }); + })); }); diff --git a/CliClient/tests/StringUtils.js b/CliClient/tests/StringUtils.js index 67e8a0101..c4b8aaf0c 100644 --- a/CliClient/tests/StringUtils.js +++ b/CliClient/tests/StringUtils.js @@ -2,8 +2,7 @@ require('app-module-path').addPath(__dirname); -const { time } = require('lib/time-utils.js'); -const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { asyncTest } = require('test-utils.js'); const StringUtils = require('lib/string-utils'); process.on('unhandledRejection', (reason, p) => { @@ -16,7 +15,7 @@ describe('StringUtils', function() { done(); }); - it('should surround keywords with strings', async (done) => { + it('should surround keywords with strings', asyncTest(async () => { const testCases = [ [[], 'test', 'a', 'b', 'test'], [['test'], 'test', 'a', 'b', 'atestb'], @@ -40,8 +39,6 @@ describe('StringUtils', function() { expect(actual).toBe(expected, `Test case ${i}`); } - - done(); - }); + })); }); diff --git a/CliClient/tests/encryption.js b/CliClient/tests/encryption.js index b00005675..be53a9e84 100644 --- a/CliClient/tests/encryption.js +++ b/CliClient/tests/encryption.js @@ -3,7 +3,7 @@ require('app-module-path').addPath(__dirname); const { time } = require('lib/time-utils.js'); -const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); const Folder = require('lib/models/Folder.js'); const Note = require('lib/models/Note.js'); const Tag = require('lib/models/Tag.js'); @@ -34,7 +34,7 @@ describe('Encryption', function() { done(); }); - it('should encode and decode header', async (done) => { + it('should encode and decode header', asyncTest(async () => { const header = { encryptionMethod: EncryptionService.METHOD_SJCL, masterKeyId: '01234568abcdefgh01234568abcdefgh', @@ -45,11 +45,9 @@ describe('Encryption', function() { delete decodedHeader.length; expect(objectsEqual(header, decodedHeader)).toBe(true); + })); - done(); - }); - - it('should generate and decrypt a master key', async (done) => { + it('should generate and decrypt a master key', asyncTest(async () => { const masterKey = await service.generateMasterKey('123456'); expect(!!masterKey.checksum).toBe(true); expect(!!masterKey.content).toBe(true); @@ -65,11 +63,9 @@ describe('Encryption', function() { const decryptedMasterKey = await service.decryptMasterKey(masterKey, '123456'); expect(decryptedMasterKey.length).toBe(512); + })); - done(); - }); - - it('should encrypt and decrypt with a master key', async (done) => { + it('should encrypt and decrypt with a master key', asyncTest(async () => { let masterKey = await service.generateMasterKey('123456'); masterKey = await MasterKey.save(masterKey); @@ -89,11 +85,9 @@ describe('Encryption', function() { const plainText2 = await service.decryptString(cipherText2); expect(plainText2 === veryLongSecret).toBe(true); + })); - done(); - }); - - it('should fail to decrypt if master key not present', async (done) => { + it('should fail to decrypt if master key not present', asyncTest(async () => { let masterKey = await service.generateMasterKey('123456'); masterKey = await MasterKey.save(masterKey); @@ -106,12 +100,10 @@ describe('Encryption', function() { let hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText)); expect(hasThrown).toBe(true); - - done(); - }); + })); - it('should fail to decrypt if data tampered with', async (done) => { + it('should fail to decrypt if data tampered with', asyncTest(async () => { let masterKey = await service.generateMasterKey('123456'); masterKey = await MasterKey.save(masterKey); @@ -123,11 +115,9 @@ describe('Encryption', function() { let hasThrown = await checkThrowAsync(async () => await service.decryptString(cipherText)); expect(hasThrown).toBe(true); + })); - done(); - }); - - it('should encrypt and decrypt notes and folders', async (done) => { + it('should encrypt and decrypt notes and folders', asyncTest(async () => { let masterKey = await service.generateMasterKey('123456'); masterKey = await MasterKey.save(masterKey); await service.loadMasterKey(masterKey, '123456', true); @@ -156,11 +146,9 @@ describe('Encryption', function() { expect(decryptedNote.body).toBe(note.body); expect(decryptedNote.id).toBe(note.id); expect(decryptedNote.parent_id).toBe(note.parent_id); + })); - done(); - }); - - it('should encrypt and decrypt files', async (done) => { + it('should encrypt and decrypt files', asyncTest(async () => { let masterKey = await service.generateMasterKey('123456'); masterKey = await MasterKey.save(masterKey); await service.loadMasterKey(masterKey, '123456', true); @@ -174,8 +162,6 @@ describe('Encryption', function() { expect(fileContentEqual(sourcePath, encryptedPath)).toBe(false); expect(fileContentEqual(sourcePath, decryptedPath)).toBe(true); - - done(); - }); + })); }); diff --git a/CliClient/tests/htmlUtils.js b/CliClient/tests/htmlUtils.js index 145b76963..34dd9b9fd 100644 --- a/CliClient/tests/htmlUtils.js +++ b/CliClient/tests/htmlUtils.js @@ -2,8 +2,7 @@ require('app-module-path').addPath(__dirname); -const { time } = require('lib/time-utils.js'); -const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { asyncTest } = require('test-utils.js'); const htmlUtils = require('lib/htmlUtils.js'); process.on('unhandledRejection', (reason, p) => { @@ -16,7 +15,7 @@ describe('htmlUtils', function() { done(); }); - it('should extract image URLs', async (done) => { + it('should extract image URLs', asyncTest(async () => { const testCases = [ ['', ['http://test.com/img.png']], [' ', ['http://test.com/img.png', 'http://test.com/img2.png']], @@ -31,11 +30,9 @@ describe('htmlUtils', function() { expect(htmlUtils.extractImageUrls(md).join(' ')).toBe(expected.join(' ')); } + })); - done(); - }); - - it('should replace image URLs', async (done) => { + it('should replace image URLs', asyncTest(async () => { const testCases = [ ['', ['http://other.com/img2.png'], ''], [' ', ['http://other.com/img2.png', 'http://other.com/img3.png'], ' '], @@ -56,11 +53,9 @@ describe('htmlUtils', function() { const r = htmlUtils.replaceImageUrls(md, callback(testCases[i][1])); expect(r.trim()).toBe(testCases[i][2].trim()); } + })); - done(); - }); - - it('should encode attributes', async (done) => { + it('should encode attributes', asyncTest(async () => { const testCases = [ [{ a: 'one', b: 'two' }, 'a="one" b="two"'], [{ a: 'one&two' }, 'a="one&two"'], @@ -71,11 +66,9 @@ describe('htmlUtils', function() { const expected = testCases[i][1]; expect(htmlUtils.attributesHtml(attrs)).toBe(expected); } + })); - done(); - }); - - it('should prepend a base URL', async (done) => { + it('should prepend a base URL', asyncTest(async () => { const testCases = [ [ 'Something', @@ -100,8 +93,6 @@ describe('htmlUtils', function() { const expected = testCases[i][2]; expect(htmlUtils.prependBaseUrl(html, baseUrl)).toBe(expected); } - - done(); - }); + })); }); diff --git a/CliClient/tests/markdownUtils.js b/CliClient/tests/markdownUtils.js index ef9c07360..6b293b8f8 100644 --- a/CliClient/tests/markdownUtils.js +++ b/CliClient/tests/markdownUtils.js @@ -2,8 +2,7 @@ require('app-module-path').addPath(__dirname); -const { time } = require('lib/time-utils.js'); -const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { asyncTest } = require('test-utils.js'); const markdownUtils = require('lib/markdownUtils.js'); process.on('unhandledRejection', (reason, p) => { @@ -16,7 +15,7 @@ describe('markdownUtils', function() { done(); }); - it('should prepend a base URL', async (done) => { + it('should prepend a base URL', asyncTest(async () => { const baseUrl = 'https://test.com/site'; const testCases = [ @@ -32,11 +31,9 @@ describe('markdownUtils', function() { const expected = testCases[i][1]; expect(markdownUtils.prependBaseUrl(md, baseUrl)).toBe(expected); } + })); - done(); - }); - - it('should extract image URLs', async (done) => { + it('should extract image URLs', asyncTest(async () => { const testCases = [ ['![something](http://test.com/img.png)', ['http://test.com/img.png']], ['![something](http://test.com/img.png) ![something2](http://test.com/img2.png)', ['http://test.com/img.png', 'http://test.com/img2.png']], @@ -50,8 +47,6 @@ describe('markdownUtils', function() { expect(markdownUtils.extractImageUrls(md).join('')).toBe(expected.join('')); } - - done(); - }); + })); }); diff --git a/CliClient/tests/models_BaseItem.js b/CliClient/tests/models_BaseItem.js index 9f0cc84c5..b138b62a8 100644 --- a/CliClient/tests/models_BaseItem.js +++ b/CliClient/tests/models_BaseItem.js @@ -29,14 +29,6 @@ describe('models_BaseItem', function() { done(); }); - // it('should be able to exclude keys when syncing', asyncTest(async () => { - // let folder1 = await Folder.save({ title: "folder1" }); - // let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id }); - // await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg'); - // let resource1 = (await Resource.all())[0]; - // console.info(await Resource.serializeForSync(resource1)); - // })); - // This is to handle the case where a property is removed from a BaseItem table - in that case files in // the sync target will still have the old property but we don't need it locally. it('should ignore properties that are present in sync file but not in database when serialising', asyncTest(async () => { diff --git a/CliClient/tests/services_rest_Api.js b/CliClient/tests/services_rest_Api.js index 03d65badb..56e891a6c 100644 --- a/CliClient/tests/services_rest_Api.js +++ b/CliClient/tests/services_rest_Api.js @@ -2,9 +2,7 @@ require('app-module-path').addPath(__dirname); -const { time } = require('lib/time-utils.js'); -const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); -const markdownUtils = require('lib/markdownUtils.js'); +const { asyncTest, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('test-utils.js'); const Api = require('lib/services/rest/Api'); const Folder = require('lib/models/Folder'); const Resource = require('lib/models/Resource'); @@ -29,27 +27,21 @@ describe('services_rest_Api', function() { done(); }); - it('should ping', async (done) => { + it('should ping', asyncTest(async () => { const response = await api.route('GET', 'ping'); - expect(response).toBe('JoplinClipperServer'); - done(); - }); + })); - it('should handle Not Found errors', async (done) => { + it('should handle Not Found errors', asyncTest(async () => { const hasThrown = await checkThrowAsync(async () => await api.route('GET', 'pong')); - expect(hasThrown).toBe(true); - done(); - }); + })); - it('should get folders', async (done) => { + it('should get folders', asyncTest(async () => { let f1 = await Folder.save({ title: 'mon carnet' }); const response = await api.route('GET', 'folders'); expect(response.length).toBe(1); - expect(response[0].title).toBe('mon carnet'); - done(); - }); + })); - it('should update folders', async (done) => { + it('should update folders', asyncTest(async () => { let f1 = await Folder.save({ title: 'mon carnet' }); const response = await api.route('PUT', `folders/${f1.id}`, null, JSON.stringify({ title: 'modifié', @@ -57,21 +49,17 @@ describe('services_rest_Api', function() { let f1b = await Folder.load(f1.id); expect(f1b.title).toBe('modifié'); + })); - done(); - }); - - it('should delete folders', async (done) => { + it('should delete folders', asyncTest(async () => { let f1 = await Folder.save({ title: 'mon carnet' }); await api.route('DELETE', `folders/${f1.id}`); let f1b = await Folder.load(f1.id); expect(!f1b).toBe(true); + })); - done(); - }); - - it('should create folders', async (done) => { + it('should create folders', asyncTest(async () => { const response = await api.route('POST', 'folders', null, JSON.stringify({ title: 'from api', })); @@ -81,22 +69,18 @@ describe('services_rest_Api', function() { let f = await Folder.all(); expect(f.length).toBe(1); expect(f[0].title).toBe('from api'); + })); - done(); - }); - - it('should get one folder', async (done) => { + it('should get one folder', asyncTest(async () => { let f1 = await Folder.save({ title: 'mon carnet' }); const response = await api.route('GET', `folders/${f1.id}`); expect(response.id).toBe(f1.id); const hasThrown = await checkThrowAsync(async () => await api.route('GET', 'folders/doesntexist')); expect(hasThrown).toBe(true); + })); - done(); - }); - - it('should get the folder notes', async (done) => { + it('should get the folder notes', asyncTest(async () => { let f1 = await Folder.save({ title: 'mon carnet' }); const response2 = await api.route('GET', `folders/${f1.id}/notes`); expect(response2.length).toBe(0); @@ -105,18 +89,14 @@ describe('services_rest_Api', function() { const n2 = await Note.save({ title: 'deux', parent_id: f1.id }); const response = await api.route('GET', `folders/${f1.id}/notes`); expect(response.length).toBe(2); + })); - done(); - }); - - it('should fail on invalid paths', async (done) => { + it('should fail on invalid paths', asyncTest(async () => { const hasThrown = await checkThrowAsync(async () => await api.route('GET', 'schtroumpf')); expect(hasThrown).toBe(true); + })); - done(); - }); - - it('should get notes', async (done) => { + it('should get notes', asyncTest(async () => { let response = null; const f1 = await Folder.save({ title: 'mon carnet' }); const f2 = await Folder.save({ title: 'mon deuxième carnet' }); @@ -134,11 +114,9 @@ describe('services_rest_Api', function() { expect(Object.getOwnPropertyNames(response).length).toBe(3); expect(response.id).toBe(n3.id); expect(response.title).toBe('trois'); + })); - done(); - }); - - it('should create notes', async (done) => { + it('should create notes', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'mon carnet' }); @@ -155,11 +133,9 @@ describe('services_rest_Api', function() { })); expect(response.title).toBe('testing'); expect(!!response.id).toBe(true); + })); - done(); - }); - - it('should preserve user timestamps when creating notes', async (done) => { + it('should preserve user timestamps when creating notes', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'mon carnet' }); @@ -174,11 +150,9 @@ describe('services_rest_Api', function() { expect(response.user_updated_time).toBe(updatedTime); expect(response.user_created_time).toBe(createdTime); + })); - done(); - }); - - it('should create notes with supplied ID', async (done) => { + it('should create notes with supplied ID', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'mon carnet' }); @@ -188,11 +162,9 @@ describe('services_rest_Api', function() { parent_id: f.id, })); expect(response.id).toBe('12345678123456781234567812345678'); + })); - done(); - }); - - it('should create todos', async (done) => { + it('should create todos', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'stuff to do' }); @@ -221,22 +193,18 @@ describe('services_rest_Api', function() { parent_id: f.id, is_todo: '1', })); - expect(response.is_todo).toBe(1); - done(); - }); + })); - it('should create folders with supplied ID', async (done) => { + it('should create folders with supplied ID', asyncTest(async () => { const response = await api.route('POST', 'folders', null, JSON.stringify({ id: '12345678123456781234567812345678', title: 'from api', })); expect(response.id).toBe('12345678123456781234567812345678'); + })); - done(); - }); - - it('should create notes with images', async (done) => { + it('should create notes with images', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'mon carnet' }); @@ -251,11 +219,9 @@ describe('services_rest_Api', function() { const resource = resources[0]; expect(response.body.indexOf(resource.id) >= 0).toBe(true); + })); - done(); - }); - - it('should delete resources', async (done) => { + it('should delete resources', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'mon carnet' }); @@ -273,11 +239,9 @@ describe('services_rest_Api', function() { await api.route('DELETE', `resources/${resource.id}`); expect(await shim.fsDriver().exists(filePath)).toBe(false); expect(!(await Resource.load(resource.id))).toBe(true); + })); - done(); - }); - - it('should create notes from HTML', async (done) => { + it('should create notes from HTML', asyncTest(async () => { let response = null; const f = await Folder.save({ title: 'mon carnet' }); @@ -288,11 +252,9 @@ describe('services_rest_Api', function() { })); expect(response.body).toBe('**Bold text**'); + })); - done(); - }); - - it('should filter fields', async (done) => { + it('should filter fields', asyncTest(async () => { let f = api.fields_({ query: { fields: 'one,two' } }, []); expect(f.length).toBe(2); expect(f[0]).toBe('one'); @@ -306,11 +268,9 @@ describe('services_rest_Api', function() { f = api.fields_({ query: { fields: ' ' } }, ['def']); expect(f.length).toBe(1); expect(f[0]).toBe('def'); + })); - done(); - }); - - it('should handle tokens', async (done) => { + it('should handle tokens', asyncTest(async () => { api = new Api('mytoken'); let hasThrown = await checkThrowAsync(async () => await api.route('GET', 'notes')); @@ -321,11 +281,9 @@ describe('services_rest_Api', function() { hasThrown = await checkThrowAsync(async () => await api.route('POST', 'notes', null, JSON.stringify({title:'testing'}))); expect(hasThrown).toBe(true); + })); - done(); - }); - - it('should add tags to notes', async (done) => { + it('should add tags to notes', asyncTest(async () => { const tag = await Tag.save({ title: 'mon étiquette' }); const note = await Note.save({ title: 'ma note' }); @@ -335,11 +293,9 @@ describe('services_rest_Api', function() { const noteIds = await Tag.noteIds(tag.id); expect(noteIds[0]).toBe(note.id); + })); - done(); - }); - - it('should remove tags from notes', async (done) => { + it('should remove tags from notes', asyncTest(async () => { const tag = await Tag.save({ title: 'mon étiquette' }); const note = await Note.save({ title: 'ma note' }); await Tag.addNote(tag.id, note.id); @@ -348,11 +304,9 @@ describe('services_rest_Api', function() { const noteIds = await Tag.noteIds(tag.id); expect(noteIds.length).toBe(0); + })); - done(); - }); - - it('should list all tag notes', async (done) => { + it('should list all tag notes', asyncTest(async () => { const tag = await Tag.save({ title: 'mon étiquette' }); const tag2 = await Tag.save({ title: 'mon étiquette 2' }); const note1 = await Note.save({ title: 'ma note un' }); @@ -370,8 +324,6 @@ describe('services_rest_Api', function() { await Tag.addNote(tag2.id, note1.id); const response3 = await api.route('GET', `notes/${note1.id}/tags`); expect(response3.length).toBe(2); - - done(); - }); + })); });