2021-05-21 15:17:21 +02:00
|
|
|
const { id, ids, createNTestFolders, sortedIds, createNTestNotes, TestApp } = require('@joplin/lib/testing/test-utils.js');
|
2020-11-07 17:59:37 +02:00
|
|
|
const BaseModel = require('@joplin/lib/BaseModel').default;
|
|
|
|
const uuid = require('@joplin/lib/uuid').default;
|
2021-01-22 19:41:11 +02:00
|
|
|
const Note = require('@joplin/lib/models/Note').default;
|
|
|
|
const Folder = require('@joplin/lib/models/Folder').default;
|
2020-05-15 13:13:42 +02:00
|
|
|
|
2020-11-07 17:59:37 +02:00
|
|
|
const { ALL_NOTES_FILTER_ID } = require('@joplin/lib/reserved-ids.js');
|
2020-05-15 13:13:42 +02:00
|
|
|
|
|
|
|
let testApp = null;
|
|
|
|
|
|
|
|
const goBackWard = (state) => {
|
|
|
|
if (!state.backwardHistoryNotes.length) return;
|
|
|
|
testApp.dispatch({ type: 'HISTORY_BACKWARD' });
|
|
|
|
};
|
|
|
|
|
|
|
|
const goForward = (state) => {
|
|
|
|
if (!state.forwardHistoryNotes.length) return;
|
|
|
|
testApp.dispatch({ type: 'HISTORY_FORWARD' });
|
|
|
|
};
|
|
|
|
|
|
|
|
const goToNote = (testApp, note) => {
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: note.id });
|
|
|
|
};
|
|
|
|
|
2020-06-04 19:26:42 +02:00
|
|
|
describe('feature_NoteHistory', function() {
|
2022-11-15 12:23:50 +02:00
|
|
|
beforeEach(async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
testApp = new TestApp();
|
|
|
|
await testApp.start(['--no-welcome']);
|
|
|
|
});
|
|
|
|
|
2022-11-15 12:23:50 +02:00
|
|
|
afterEach(async () => {
|
2022-07-23 09:31:32 +02:00
|
|
|
if (testApp) await testApp.destroy();
|
2020-05-15 13:13:42 +02:00
|
|
|
testApp = null;
|
|
|
|
});
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should save history when navigating through notes', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
// setup
|
|
|
|
const folders = await createNTestFolders(2);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
// let notes1 = await createNTestNotes(5, folders[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[3].id });
|
|
|
|
await testApp.wait();
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[2].id });
|
|
|
|
await testApp.wait();
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[1].id });
|
|
|
|
await testApp.wait();
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[0].id });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[1].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[1].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[4].id });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[4].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should save history when navigating through notebooks', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(2);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
const notes1 = await createNTestNotes(5, folders[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[1]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes1[4].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[1].id);
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[4].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes1[4].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[1].id);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[4].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should save history when searching for a note', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(2);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
const notes1 = await createNTestNotes(5, folders[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[1]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes1[4].id]); // notes1[4]
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[1].id);
|
|
|
|
|
|
|
|
const searchId = uuid.create();
|
|
|
|
testApp.dispatch({
|
|
|
|
type: 'SEARCH_UPDATE',
|
|
|
|
search: {
|
|
|
|
id: searchId,
|
|
|
|
title: notes0[0].title,
|
|
|
|
query_pattern: notes0[0].title,
|
|
|
|
query_folder_id: null,
|
|
|
|
type: BaseModel.TYPE_SEARCH,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({
|
|
|
|
type: 'SEARCH_SELECT',
|
|
|
|
id: searchId,
|
|
|
|
});
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(ids(state.backwardHistoryNotes)).toEqual(ids([notes0[4], notes1[4]]));
|
|
|
|
expect(ids(state.forwardHistoryNotes)).toEqual([]);
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should ensure no adjacent duplicates', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(2);
|
2020-06-05 17:05:47 +02:00
|
|
|
const notes0 = await createNTestNotes(3, folders[0]);
|
2020-05-15 13:13:42 +02:00
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[0].id });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
goToNote(testApp, notes0[2]);
|
|
|
|
await testApp.wait();
|
2020-06-05 17:05:47 +02:00
|
|
|
goToNote(testApp, notes0[1]);
|
2020-05-15 13:13:42 +02:00
|
|
|
await testApp.wait();
|
|
|
|
goToNote(testApp, notes0[2]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
2020-06-05 17:05:47 +02:00
|
|
|
testApp.dispatch({ type: 'NOTE_DELETE', id: notes0[1].id });
|
|
|
|
await testApp.wait();
|
2020-05-15 13:13:42 +02:00
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
2020-06-05 17:05:47 +02:00
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[0].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
2020-05-15 13:13:42 +02:00
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should ensure history is not corrupted when notes get deleted.', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(2);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'NOTE_SELECT', id: notes0[0].id });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[2]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'NOTE_DELETE', id: notes0[1].id });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[0].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should ensure history is not corrupted when notes get created.', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(2);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[0]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
const newNote = await Note.save({
|
|
|
|
parent_id: folders[0].id,
|
|
|
|
is_todo: 0,
|
|
|
|
body: 'test',
|
|
|
|
});
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, newNote);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([newNote.id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[2]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([newNote.id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[1].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([newNote.id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
expect(state.selectedFolderId).toEqual(folders[0].id);
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should ensure history works when traversing all notes', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(2);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
const notes1 = await createNTestNotes(5, folders[1]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: id(folders[0]) });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[0]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
testApp.dispatch({ type: 'SMART_FILTER_SELECT', id: ALL_NOTES_FILTER_ID });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
expect(sortedIds(state.notes)).toEqual(sortedIds(notes0.concat(notes1)));
|
|
|
|
expect(state.selectedNoteIds).toEqual(ids([notes0[0]]));
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[2]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes0[4]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, notes1[2]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes1[2].id]);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[4].id]);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[0].id]);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[2].id]);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedNoteIds).toEqual([notes0[4].id]);
|
|
|
|
}));
|
|
|
|
|
2020-12-01 20:05:24 +02:00
|
|
|
it('should ensure history works when traversing through conflict notes', (async () => {
|
2020-05-15 13:13:42 +02:00
|
|
|
const folders = await createNTestFolders(1);
|
|
|
|
await testApp.wait();
|
|
|
|
const notes0 = await createNTestNotes(5, folders[0]);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
// create two conflict notes with parent_id folder 1
|
|
|
|
const note1 = await Note.save({ title: 'note 1', parent_id: folders[0].id, is_conflict: 1 });
|
|
|
|
await testApp.wait();
|
|
|
|
const note2 = await Note.save({ title: 'note 2', parent_id: folders[0].id, is_conflict: 1 });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
// Testing history between conflict notes
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: Folder.conflictFolderId() });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, note1);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
goToNote(testApp, note2);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
let state = testApp.store().getState();
|
|
|
|
expect(state.selectedFolderId).toBe(Folder.conflictFolderId());
|
|
|
|
expect(state.selectedNoteIds[0]).toBe(note2.id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedFolderId).toBe(Folder.conflictFolderId());
|
|
|
|
expect(state.selectedNoteIds[0]).toBe(note1.id);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedFolderId).toBe(Folder.conflictFolderId());
|
|
|
|
expect(state.selectedNoteIds[0]).toBe(note2.id);
|
|
|
|
|
|
|
|
// Testing history between conflict and non conflict notes.
|
|
|
|
testApp.dispatch({ type: 'FOLDER_SELECT', id: folders[0].id });
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedFolderId).toBe(folders[0].id);
|
|
|
|
expect(state.selectedNoteIds[0]).toBe(notes0[4].id);
|
|
|
|
|
|
|
|
goBackWard(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedFolderId).toBe(Folder.conflictFolderId());
|
|
|
|
expect(state.selectedNoteIds[0]).toBe(note2.id);
|
|
|
|
|
|
|
|
goForward(state);
|
|
|
|
await testApp.wait();
|
|
|
|
|
|
|
|
state = testApp.store().getState();
|
|
|
|
expect(state.selectedFolderId).toBe(folders[0].id);
|
|
|
|
expect(state.selectedNoteIds[0]).toBe(notes0[4].id);
|
|
|
|
}));
|
|
|
|
|
|
|
|
});
|