diff --git a/CliClient/tests/models_Folder.js b/CliClient/tests/models_Folder.js index ff132b7eb9..a96b861704 100644 --- a/CliClient/tests/models_Folder.js +++ b/CliClient/tests/models_Folder.js @@ -3,7 +3,7 @@ require('app-module-path').addPath(__dirname); const { time } = require('lib/time-utils.js'); -const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { createNTestNotes, 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 BaseModel = require('lib/BaseModel.js'); @@ -46,7 +46,14 @@ describe('models_Folder', function() { it('should recursively delete notes and sub-notebooks', asyncTest(async () => { const f1 = await Folder.save({ title: 'folder1' }); const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); - const n1 = await Note.save({ title: 'note1', parent_id: f2.id }); + const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id }); + const f4 = await Folder.save({ title: 'folder4', parent_id: f1.id }); + + const noOfNotes = 20; + await createNTestNotes(noOfNotes, f1, null, 'note1'); + await createNTestNotes(noOfNotes, f2, null, 'note2'); + await createNTestNotes(noOfNotes, f3, null, 'note3'); + await createNTestNotes(noOfNotes, f4, null, 'note4'); await Folder.delete(f1.id); diff --git a/CliClient/tests/models_Note.js b/CliClient/tests/models_Note.js index 06e0f259db..55435e24af 100644 --- a/CliClient/tests/models_Note.js +++ b/CliClient/tests/models_Note.js @@ -3,7 +3,7 @@ require('app-module-path').addPath(__dirname); const { time } = require('lib/time-utils.js'); -const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js'); +const { sortedIds, createNTestNotes, 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 BaseModel = require('lib/BaseModel.js'); @@ -14,8 +14,13 @@ process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); }); -describe('models_Note', function() { +async function allItems() { + const folders = await Folder.all(); + const notes = await Note.all(); + return folders.concat(notes); +} +describe('models_Note', function() { beforeEach(async (done) => { await setupDatabaseAndSynchronizer(1); await switchClient(1); @@ -129,4 +134,65 @@ describe('models_Note', function() { expect(duplicatedNote.user_updated_time !== note1.user_updated_time).toBe(true); })); + it('should delete a set of notes', asyncTest(async () => { + const folder1 = await Folder.save({ title: 'folder1' }); + const noOfNotes = 20; + await createNTestNotes(noOfNotes, folder1); + + const noteIds = await Folder.noteIds(folder1.id); + await Note.batchDelete(noteIds); + + const all = await allItems(); + expect(all.length).toBe(1); + expect(all[0].id).toBe(folder1.id); + })); + + it('should delete only the selected notes', asyncTest(async () => { + const f1 = await Folder.save({ title: 'folder1' }); + const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); + + const noOfNotes = 20; + await createNTestNotes(noOfNotes, f1, null, 'note1'); + await createNTestNotes(noOfNotes, f2, null, 'note1'); + + const allBeforeDelete = await allItems(); + + const notesInFolder1IDs = await Folder.noteIds(f1.id); + const notesInFolder2IDs = await Folder.noteIds(f2.id); + + const notesToRemoveFromFolder1 = notesInFolder1IDs.slice(0, 6); + const notesToRemoveFromFolder2 = notesInFolder2IDs.slice(11, 14); + + await Note.batchDelete(notesToRemoveFromFolder1); + await Note.batchDelete(notesToRemoveFromFolder2); + + const allAfterDelete = await allItems(); + + const expectedLength = allBeforeDelete.length - notesToRemoveFromFolder1.length - notesToRemoveFromFolder2.length; + expect(allAfterDelete.length).toBe(expectedLength); + + // Common elements between the to-be-deleted notes and the notes and folders remaining after the delete + const intersection = [...notesToRemoveFromFolder1, ...notesToRemoveFromFolder2].filter(x => allAfterDelete.includes(x)); + // Should be empty + expect(intersection.length).toBe(0); + })); + + it('should delete nothing', asyncTest(async () => { + const f1 = await Folder.save({ title: 'folder1' }); + const f2 = await Folder.save({ title: 'folder2', parent_id: f1.id }); + const f3 = await Folder.save({ title: 'folder3', parent_id: f2.id }); + const f4 = await Folder.save({ title: 'folder4', parent_id: f1.id }); + + const noOfNotes = 20; + await createNTestNotes(noOfNotes, f1, null, 'note1'); + await createNTestNotes(noOfNotes, f2, null, 'note2'); + await createNTestNotes(noOfNotes, f3, null, 'note3'); + await createNTestNotes(noOfNotes, f4, null, 'note4'); + + const beforeDelete = await allItems(); + await Note.batchDelete([]); + const afterDelete = await allItems(); + + expect(sortedIds(afterDelete)).toEqual(sortedIds(beforeDelete)); + })); }); diff --git a/ReactNativeClient/lib/models/Folder.js b/ReactNativeClient/lib/models/Folder.js index 9c8a23c327..37296d64d2 100644 --- a/ReactNativeClient/lib/models/Folder.js +++ b/ReactNativeClient/lib/models/Folder.js @@ -68,9 +68,7 @@ class Folder extends BaseItem { if (options.deleteChildren) { const noteIds = await Folder.noteIds(folderId); - for (let i = 0; i < noteIds.length; i++) { - await Note.delete(noteIds[i]); - } + await Note.batchDelete(noteIds); const subFolderIds = await Folder.subFolderIds(folderId); for (let i = 0; i < subFolderIds.length; i++) {