mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Fixed tags and added unit tests
This commit is contained in:
parent
ab312d70f5
commit
dde3ea2008
@ -5,7 +5,7 @@ rm -f "$CLIENT_DIR/tests-build/lib"
|
|||||||
mkdir -p "$CLIENT_DIR/tests-build/data"
|
mkdir -p "$CLIENT_DIR/tests-build/data"
|
||||||
ln -s "$CLIENT_DIR/build/lib" "$CLIENT_DIR/tests-build"
|
ln -s "$CLIENT_DIR/build/lib" "$CLIENT_DIR/tests-build"
|
||||||
|
|
||||||
npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/synchronizer.js tests-build/base-model.js
|
npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/synchronizer.js
|
||||||
|
|
||||||
#npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/synchronizer.js
|
#npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/synchronizer.js
|
||||||
#npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/base-model.js
|
#npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/base-model.js
|
@ -3,6 +3,7 @@ import { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi,
|
|||||||
import { createFoldersAndNotes } from 'test-data.js';
|
import { createFoldersAndNotes } from 'test-data.js';
|
||||||
import { Folder } from 'lib/models/folder.js';
|
import { Folder } from 'lib/models/folder.js';
|
||||||
import { Note } from 'lib/models/note.js';
|
import { Note } from 'lib/models/note.js';
|
||||||
|
import { Tag } from 'lib/models/tag.js';
|
||||||
import { Setting } from 'lib/models/setting.js';
|
import { Setting } from 'lib/models/setting.js';
|
||||||
import { BaseItem } from 'lib/models/base-item.js';
|
import { BaseItem } from 'lib/models/base-item.js';
|
||||||
import { BaseModel } from 'lib/base-model.js';
|
import { BaseModel } from 'lib/base-model.js';
|
||||||
@ -461,4 +462,43 @@ describe('Synchronizer', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should sync tags', async (done) => {
|
||||||
|
let f1 = await Folder.save({ title: "folder" });
|
||||||
|
let n1 = await Note.save({ title: "mynote" });
|
||||||
|
let n2 = await Note.save({ title: "mynote2" });
|
||||||
|
let tag = await Tag.save({ title: 'mytag' });
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
|
await switchClient(2);
|
||||||
|
|
||||||
|
await synchronizer().start();
|
||||||
|
let remoteTag = await Tag.loadByTitle(tag.title);
|
||||||
|
expect(!!remoteTag).toBe(true);
|
||||||
|
expect(remoteTag.id).toBe(tag.id);
|
||||||
|
await Tag.addNote(remoteTag.id, n1.id);
|
||||||
|
await Tag.addNote(remoteTag.id, n2.id);
|
||||||
|
let noteIds = await Tag.tagNoteIds(tag.id);
|
||||||
|
expect(noteIds.length).toBe(2);
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
|
await switchClient(1);
|
||||||
|
|
||||||
|
await synchronizer().start();
|
||||||
|
let remoteNoteIds = await Tag.tagNoteIds(tag.id);
|
||||||
|
expect(remoteNoteIds.length).toBe(2);
|
||||||
|
Tag.removeNote(tag.id, n1.id);
|
||||||
|
remoteNoteIds = await Tag.tagNoteIds(tag.id);
|
||||||
|
expect(remoteNoteIds.length).toBe(1);
|
||||||
|
await synchronizer().start();
|
||||||
|
|
||||||
|
await switchClient(2);
|
||||||
|
|
||||||
|
await synchronizer().start();
|
||||||
|
noteIds = await Tag.tagNoteIds(tag.id);
|
||||||
|
expect(noteIds.length).toBe(1);
|
||||||
|
expect(remoteNoteIds[0]).toBe(noteIds[0]);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -10,6 +10,7 @@ import { BaseItem } from 'lib/models/base-item.js';
|
|||||||
import { Synchronizer } from 'lib/synchronizer.js';
|
import { Synchronizer } from 'lib/synchronizer.js';
|
||||||
import { FileApi } from 'lib/file-api.js';
|
import { FileApi } from 'lib/file-api.js';
|
||||||
import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js';
|
import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js';
|
||||||
|
import { time } from 'lib/time-utils.js';
|
||||||
|
|
||||||
let databases_ = [];
|
let databases_ = [];
|
||||||
let synchronizers_ = [];
|
let synchronizers_ = [];
|
||||||
@ -29,8 +30,9 @@ function sleep(n) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchClient(id) {
|
async function switchClient(id) {
|
||||||
Setting.saveAll();
|
await time.msleep(200);
|
||||||
|
await Setting.saveAll();
|
||||||
|
|
||||||
currentClient_ = id;
|
currentClient_ = id;
|
||||||
BaseModel.db_ = databases_[id];
|
BaseModel.db_ = databases_[id];
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"CliClient/app/src",
|
"CliClient/app/src",
|
||||||
"CliClient/app/lib",
|
"CliClient/app/lib",
|
||||||
"CliClient/tests/src",
|
"CliClient/tests/src",
|
||||||
|
"CliClient/tests/fuzzing",
|
||||||
"ReactNativeClient/node_modules",
|
"ReactNativeClient/node_modules",
|
||||||
"ReactNativeClient/android/app/build",
|
"ReactNativeClient/android/app/build",
|
||||||
"ReactNativeClient/android/build",
|
"ReactNativeClient/android/build",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { BaseModel } from 'lib/base-model.js';
|
import { BaseModel } from 'lib/base-model.js';
|
||||||
import { Database } from 'lib/database.js';
|
import { Database } from 'lib/database.js';
|
||||||
import { BaseItem } from 'lib/models/base-item.js';
|
import { BaseItem } from 'lib/models/base-item.js';
|
||||||
|
import { time } from 'lib/time-utils.js';
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
|
|
||||||
class Tag extends BaseItem {
|
class Tag extends BaseItem {
|
||||||
@ -18,7 +19,6 @@ class Tag extends BaseItem {
|
|||||||
fieldNames.push('type_');
|
fieldNames.push('type_');
|
||||||
fieldNames.push(async () => {
|
fieldNames.push(async () => {
|
||||||
let noteIds = await this.tagNoteIds(item.id);
|
let noteIds = await this.tagNoteIds(item.id);
|
||||||
console.info('NOTE IDS', noteIds);
|
|
||||||
return {
|
return {
|
||||||
key: 'notes_',
|
key: 'notes_',
|
||||||
value: noteIds.join(','),
|
value: noteIds.join(','),
|
||||||
@ -37,10 +37,6 @@ class Tag extends BaseItem {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: in order for a sync to happen, the updated_time property should somehow be changed
|
|
||||||
// whenever an tag is applied or removed from an item. Either the updated_time property
|
|
||||||
// is changed here or by the caller?
|
|
||||||
|
|
||||||
static async addNote(tagId, noteId) {
|
static async addNote(tagId, noteId) {
|
||||||
let hasIt = await this.hasNote(tagId, noteId);
|
let hasIt = await this.hasNote(tagId, noteId);
|
||||||
if (hasIt) return;
|
if (hasIt) return;
|
||||||
@ -51,18 +47,17 @@ class Tag extends BaseItem {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await this.db().exec(query);
|
await this.db().exec(query);
|
||||||
//await this.save({ id: tagId, updated_time: time.unixMs() }); //type_: BaseModel.MODEL_TYPE_TAG
|
await this.save({ id: tagId, updated_time: time.unixMs() });
|
||||||
}
|
}
|
||||||
|
|
||||||
static async addNotes(tagId, noteIds) {
|
static async removeNote(tagId, noteId) {
|
||||||
for (let i = 0; i < noteIds.length; i++) {
|
await this.db().exec('DELETE FROM note_tags WHERE tag_id = ? AND note_id = ?', [tagId, noteId]);
|
||||||
await this.addNote(tagId, noteIds[i]);
|
await this.save({ id: tagId, updated_time: time.unixMs() });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: updated_time must not change since this is only called from
|
// Note: updated_time must not change here since this is only called from
|
||||||
// the synchronizer, which manages and sets the correct updated_time
|
// save(), which already handles how the updated_time property is set.
|
||||||
static async setAssociatedNotes(tagId, noteIds) {
|
static async setAssociatedNotes_(tagId, noteIds) {
|
||||||
let queries = [{
|
let queries = [{
|
||||||
sql: 'DELETE FROM note_tags WHERE tag_id = ?',
|
sql: 'DELETE FROM note_tags WHERE tag_id = ?',
|
||||||
params: [tagId],
|
params: [tagId],
|
||||||
@ -80,8 +75,17 @@ class Tag extends BaseItem {
|
|||||||
return !!r;
|
return !!r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static removeNote(tagId, noteId) {
|
static async save(o, options = null) {
|
||||||
return this.db().exec('DELETE FROM note_tags WHERE tag_id = ? AND note_id = ?', [tagId, noteId]);
|
let result = await super.save(o, options);
|
||||||
|
|
||||||
|
if (options && options.applyMetadataChanges === true) {
|
||||||
|
if (o.notes_) {
|
||||||
|
let noteIds = o.notes_.split(',');
|
||||||
|
await this.setAssociatedNotes_(o.id, noteIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,10 @@ class Synchronizer {
|
|||||||
|
|
||||||
let newContent = Object.assign({}, content);
|
let newContent = Object.assign({}, content);
|
||||||
newContent.sync_time = time.unixMs();
|
newContent.sync_time = time.unixMs();
|
||||||
let options = { autoTimestamp: false };
|
let options = {
|
||||||
|
autoTimestamp: false,
|
||||||
|
applyMetadataChanges: true,
|
||||||
|
};
|
||||||
if (action == 'createLocal') options.isNew = true;
|
if (action == 'createLocal') options.isNew = true;
|
||||||
|
|
||||||
if (newContent.type_ == BaseModel.MODEL_TYPE_RESOURCE && action == 'createLocal') {
|
if (newContent.type_ == BaseModel.MODEL_TYPE_RESOURCE && action == 'createLocal') {
|
||||||
@ -321,11 +324,6 @@ class Synchronizer {
|
|||||||
|
|
||||||
await ItemClass.save(newContent, options);
|
await ItemClass.save(newContent, options);
|
||||||
|
|
||||||
if (newContent.type_ == BaseModel.MODEL_TYPE_TAG) {
|
|
||||||
let noteIds = newContent.notes_.split(',');
|
|
||||||
await ItemClass.setAssociatedNotes(newContent.id, noteIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logSyncOperation(action, local, content, reason);
|
this.logSyncOperation(action, local, content, reason);
|
||||||
} else {
|
} else {
|
||||||
this.logSyncOperation(action, local, remote, reason);
|
this.logSyncOperation(action, local, remote, reason);
|
||||||
|
Loading…
Reference in New Issue
Block a user