mirror of https://github.com/laurent22/joplin.git
291 lines
14 KiB
JavaScript
291 lines
14 KiB
JavaScript
'use strict';
|
|
const __awaiter = (this && this.__awaiter) || function(thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function(resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function(resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator['throw'](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
const Setting_1 = require('@joplin/lib/models/Setting');
|
|
const test_utils_synchronizer_1 = require('./test-utils-synchronizer');
|
|
const { syncTargetName, afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, synchronizer, sleep, switchClient, syncTargetId, fileApi } = require('./test-utils.js');
|
|
const Folder_1 = require('@joplin/lib/models/Folder');
|
|
const Note_1 = require('@joplin/lib/models/Note');
|
|
const BaseItem_1 = require('@joplin/lib/models/BaseItem');
|
|
const WelcomeUtils = require('@joplin/lib/WelcomeUtils');
|
|
describe('Synchronizer.basics', function() {
|
|
beforeEach((done) => __awaiter(this, void 0, void 0, function* () {
|
|
yield setupDatabaseAndSynchronizer(1);
|
|
yield setupDatabaseAndSynchronizer(2);
|
|
yield switchClient(1);
|
|
done();
|
|
}));
|
|
afterAll(() => __awaiter(this, void 0, void 0, function* () {
|
|
yield afterAllCleanUp();
|
|
}));
|
|
it('should create remote items', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder = yield Folder_1.default.save({ title: 'folder1' });
|
|
yield Note_1.default.save({ title: 'un', parent_id: folder.id });
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield synchronizerStart();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
|
|
})));
|
|
it('should update remote items', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder = yield Folder_1.default.save({ title: 'folder1' });
|
|
const note = yield Note_1.default.save({ title: 'un', parent_id: folder.id });
|
|
yield synchronizerStart();
|
|
yield Note_1.default.save({ title: 'un UPDATE', id: note.id });
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield synchronizerStart();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
|
|
})));
|
|
it('should create local items', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder = yield Folder_1.default.save({ title: 'folder1' });
|
|
yield Note_1.default.save({ title: 'un', parent_id: folder.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
|
|
})));
|
|
it('should update local items', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
const note1 = yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield sleep(0.1);
|
|
let note2 = yield Note_1.default.load(note1.id);
|
|
note2.title = 'Updated on client 2';
|
|
yield Note_1.default.save(note2);
|
|
note2 = yield Note_1.default.load(note2.id);
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield synchronizerStart();
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
|
|
})));
|
|
it('should delete remote notes', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
const note1 = yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield sleep(0.1);
|
|
yield Note_1.default.delete(note1.id);
|
|
yield synchronizerStart();
|
|
const remotes = yield test_utils_synchronizer_1.remoteNotesAndFolders();
|
|
expect(remotes.length).toBe(1);
|
|
expect(remotes[0].id).toBe(folder1.id);
|
|
const deletedItems = yield BaseItem_1.default.deletedItems(syncTargetId());
|
|
expect(deletedItems.length).toBe(0);
|
|
})));
|
|
it('should not created deleted_items entries for items deleted via sync', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield Folder_1.default.delete(folder1.id);
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield synchronizerStart();
|
|
const deletedItems = yield BaseItem_1.default.deletedItems(syncTargetId());
|
|
expect(deletedItems.length).toBe(0);
|
|
})));
|
|
it('should delete local notes', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
const note1 = yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
|
|
const note2 = yield Note_1.default.save({ title: 'deux', parent_id: folder1.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield Note_1.default.delete(note1.id);
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield synchronizerStart();
|
|
const items = yield test_utils_synchronizer_1.allNotesFolders();
|
|
expect(items.length).toBe(2);
|
|
const deletedItems = yield BaseItem_1.default.deletedItems(syncTargetId());
|
|
expect(deletedItems.length).toBe(0);
|
|
yield Note_1.default.delete(note2.id);
|
|
yield synchronizerStart();
|
|
})));
|
|
it('should delete remote folder', (() => __awaiter(this, void 0, void 0, function* () {
|
|
yield Folder_1.default.save({ title: 'folder1' });
|
|
const folder2 = yield Folder_1.default.save({ title: 'folder2' });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield sleep(0.1);
|
|
yield Folder_1.default.delete(folder2.id);
|
|
yield synchronizerStart();
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
|
|
})));
|
|
it('should delete local folder', (() => __awaiter(this, void 0, void 0, function* () {
|
|
yield Folder_1.default.save({ title: 'folder1' });
|
|
const folder2 = yield Folder_1.default.save({ title: 'folder2' });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield Folder_1.default.delete(folder2.id);
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield synchronizerStart();
|
|
const items = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(items, expect);
|
|
})));
|
|
it('should cross delete all folders', (() => __awaiter(this, void 0, void 0, function* () {
|
|
// If client1 and 2 have two folders, client 1 deletes item 1 and client
|
|
// 2 deletes item 2, they should both end up with no items after sync.
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
const folder2 = yield Folder_1.default.save({ title: 'folder2' });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield sleep(0.1);
|
|
yield Folder_1.default.delete(folder1.id);
|
|
yield switchClient(1);
|
|
yield Folder_1.default.delete(folder2.id);
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
const items2 = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield switchClient(1);
|
|
yield synchronizerStart();
|
|
const items1 = yield test_utils_synchronizer_1.allNotesFolders();
|
|
expect(items1.length).toBe(0);
|
|
expect(items1.length).toBe(items2.length);
|
|
})));
|
|
it('items should be downloaded again when user cancels in the middle of delta operation', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
yield Note_1.default.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
synchronizer().testingHooks_ = ['cancelDeltaLoop2'];
|
|
yield synchronizerStart();
|
|
let notes = yield Note_1.default.all();
|
|
expect(notes.length).toBe(0);
|
|
synchronizer().testingHooks_ = [];
|
|
yield synchronizerStart();
|
|
notes = yield Note_1.default.all();
|
|
expect(notes.length).toBe(1);
|
|
})));
|
|
it('should skip items that cannot be synced', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
|
|
const note1 = yield Note_1.default.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
|
|
const noteId = note1.id;
|
|
yield synchronizerStart();
|
|
let disabledItems = yield BaseItem_1.default.syncDisabledItems(syncTargetId());
|
|
expect(disabledItems.length).toBe(0);
|
|
yield Note_1.default.save({ id: noteId, title: 'un mod' });
|
|
synchronizer().testingHooks_ = ['notesRejectedByTarget'];
|
|
yield synchronizerStart();
|
|
synchronizer().testingHooks_ = [];
|
|
yield synchronizerStart(); // Another sync to check that this item is now excluded from sync
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
const notes = yield Note_1.default.all();
|
|
expect(notes.length).toBe(1);
|
|
expect(notes[0].title).toBe('un');
|
|
yield switchClient(1);
|
|
disabledItems = yield BaseItem_1.default.syncDisabledItems(syncTargetId());
|
|
expect(disabledItems.length).toBe(1);
|
|
})));
|
|
it('should allow duplicate folder titles', (() => __awaiter(this, void 0, void 0, function* () {
|
|
yield Folder_1.default.save({ title: 'folder' });
|
|
yield switchClient(2);
|
|
let remoteF2 = yield Folder_1.default.save({ title: 'folder' });
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield sleep(0.1);
|
|
yield synchronizerStart();
|
|
const localF2 = yield Folder_1.default.load(remoteF2.id);
|
|
expect(localF2.title == remoteF2.title).toBe(true);
|
|
// Then that folder that has been renamed locally should be set in such a way
|
|
// that synchronizing it applies the title change remotely, and that new title
|
|
// should be retrieved by client 2.
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield sleep(0.1);
|
|
yield synchronizerStart();
|
|
remoteF2 = yield Folder_1.default.load(remoteF2.id);
|
|
expect(remoteF2.title == localF2.title).toBe(true);
|
|
})));
|
|
it('should create remote items with UTF-8 content', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder = yield Folder_1.default.save({ title: 'Fahrräder' });
|
|
yield Note_1.default.save({ title: 'Fahrräder', body: 'Fahrräder', parent_id: folder.id });
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
yield synchronizerStart();
|
|
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
|
|
})));
|
|
it('should update remote items but not pull remote changes', (() => __awaiter(this, void 0, void 0, function* () {
|
|
const folder = yield Folder_1.default.save({ title: 'folder1' });
|
|
const note = yield Note_1.default.save({ title: 'un', parent_id: folder.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
yield Note_1.default.save({ title: 'deux', parent_id: folder.id });
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield Note_1.default.save({ title: 'un UPDATE', id: note.id });
|
|
yield synchronizerStart(null, { syncSteps: ['update_remote'] });
|
|
const all = yield test_utils_synchronizer_1.allNotesFolders();
|
|
expect(all.length).toBe(2);
|
|
yield switchClient(2);
|
|
yield synchronizerStart();
|
|
const note2 = yield Note_1.default.load(note.id);
|
|
expect(note2.title).toBe('un UPDATE');
|
|
})));
|
|
it('should create a new Welcome notebook on each client', (() => __awaiter(this, void 0, void 0, function* () {
|
|
// Create the Welcome items on two separate clients
|
|
yield WelcomeUtils.createWelcomeItems();
|
|
yield synchronizerStart();
|
|
yield switchClient(2);
|
|
yield WelcomeUtils.createWelcomeItems();
|
|
const beforeFolderCount = (yield Folder_1.default.all()).length;
|
|
const beforeNoteCount = (yield Note_1.default.all()).length;
|
|
expect(beforeFolderCount === 1).toBe(true);
|
|
expect(beforeNoteCount > 1).toBe(true);
|
|
yield synchronizerStart();
|
|
const afterFolderCount = (yield Folder_1.default.all()).length;
|
|
const afterNoteCount = (yield Note_1.default.all()).length;
|
|
expect(afterFolderCount).toBe(beforeFolderCount * 2);
|
|
expect(afterNoteCount).toBe(beforeNoteCount * 2);
|
|
// Changes to the Welcome items should be synced to all clients
|
|
const f1 = (yield Folder_1.default.all())[0];
|
|
yield Folder_1.default.save({ id: f1.id, title: 'Welcome MOD' });
|
|
yield synchronizerStart();
|
|
yield switchClient(1);
|
|
yield synchronizerStart();
|
|
const f1_1 = yield Folder_1.default.load(f1.id);
|
|
expect(f1_1.title).toBe('Welcome MOD');
|
|
})));
|
|
it('should not wipe out user data when syncing with an empty target', (() => __awaiter(this, void 0, void 0, function* () {
|
|
// Only these targets support the wipeOutFailSafe flag (in other words, the targets that use basicDelta)
|
|
if (!['nextcloud', 'memory', 'filesystem', 'amazon_s3'].includes(syncTargetName())) { return; }
|
|
for (let i = 0; i < 10; i++) { yield Note_1.default.save({ title: 'note' }); }
|
|
Setting_1.default.setValue('sync.wipeOutFailSafe', true);
|
|
yield synchronizerStart();
|
|
yield fileApi().clearRoot(); // oops
|
|
yield synchronizerStart();
|
|
expect((yield Note_1.default.all()).length).toBe(10); // but since the fail-safe if on, the notes have not been deleted
|
|
Setting_1.default.setValue('sync.wipeOutFailSafe', false); // Now switch it off
|
|
yield synchronizerStart();
|
|
expect((yield Note_1.default.all()).length).toBe(0); // Since the fail-safe was off, the data has been cleared
|
|
// Handle case where the sync target has been wiped out, then the user creates one note and sync.
|
|
for (let i = 0; i < 10; i++) { yield Note_1.default.save({ title: 'note' }); }
|
|
Setting_1.default.setValue('sync.wipeOutFailSafe', true);
|
|
yield synchronizerStart();
|
|
yield fileApi().clearRoot();
|
|
yield Note_1.default.save({ title: 'ma note encore' });
|
|
yield synchronizerStart();
|
|
expect((yield Note_1.default.all()).length).toBe(11);
|
|
})));
|
|
});
|
|
// # sourceMappingURL=Synchronizer.share.js.map
|