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"
|
||||
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/base-model.js
|
@ -3,6 +3,7 @@ import { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi,
|
||||
import { createFoldersAndNotes } from 'test-data.js';
|
||||
import { Folder } from 'lib/models/folder.js';
|
||||
import { Note } from 'lib/models/note.js';
|
||||
import { Tag } from 'lib/models/tag.js';
|
||||
import { Setting } from 'lib/models/setting.js';
|
||||
import { BaseItem } from 'lib/models/base-item.js';
|
||||
import { BaseModel } from 'lib/base-model.js';
|
||||
@ -460,5 +461,44 @@ describe('Synchronizer', function() {
|
||||
|
||||
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 { FileApi } from 'lib/file-api.js';
|
||||
import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js';
|
||||
import { time } from 'lib/time-utils.js';
|
||||
|
||||
let databases_ = [];
|
||||
let synchronizers_ = [];
|
||||
@ -29,8 +30,9 @@ function sleep(n) {
|
||||
});
|
||||
}
|
||||
|
||||
function switchClient(id) {
|
||||
Setting.saveAll();
|
||||
async function switchClient(id) {
|
||||
await time.msleep(200);
|
||||
await Setting.saveAll();
|
||||
|
||||
currentClient_ = id;
|
||||
BaseModel.db_ = databases_[id];
|
||||
|
@ -15,6 +15,7 @@
|
||||
"CliClient/app/src",
|
||||
"CliClient/app/lib",
|
||||
"CliClient/tests/src",
|
||||
"CliClient/tests/fuzzing",
|
||||
"ReactNativeClient/node_modules",
|
||||
"ReactNativeClient/android/app/build",
|
||||
"ReactNativeClient/android/build",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { BaseModel } from 'lib/base-model.js';
|
||||
import { Database } from 'lib/database.js';
|
||||
import { BaseItem } from 'lib/models/base-item.js';
|
||||
import { time } from 'lib/time-utils.js';
|
||||
import lodash from 'lodash';
|
||||
|
||||
class Tag extends BaseItem {
|
||||
@ -18,7 +19,6 @@ class Tag extends BaseItem {
|
||||
fieldNames.push('type_');
|
||||
fieldNames.push(async () => {
|
||||
let noteIds = await this.tagNoteIds(item.id);
|
||||
console.info('NOTE IDS', noteIds);
|
||||
return {
|
||||
key: 'notes_',
|
||||
value: noteIds.join(','),
|
||||
@ -37,10 +37,6 @@ class Tag extends BaseItem {
|
||||
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) {
|
||||
let hasIt = await this.hasNote(tagId, noteId);
|
||||
if (hasIt) return;
|
||||
@ -51,18 +47,17 @@ class Tag extends BaseItem {
|
||||
});
|
||||
|
||||
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) {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
await this.addNote(tagId, noteIds[i]);
|
||||
}
|
||||
static async removeNote(tagId, noteId) {
|
||||
await this.db().exec('DELETE FROM note_tags WHERE tag_id = ? AND note_id = ?', [tagId, noteId]);
|
||||
await this.save({ id: tagId, updated_time: time.unixMs() });
|
||||
}
|
||||
|
||||
// Note: updated_time must not change since this is only called from
|
||||
// the synchronizer, which manages and sets the correct updated_time
|
||||
static async setAssociatedNotes(tagId, noteIds) {
|
||||
// Note: updated_time must not change here since this is only called from
|
||||
// save(), which already handles how the updated_time property is set.
|
||||
static async setAssociatedNotes_(tagId, noteIds) {
|
||||
let queries = [{
|
||||
sql: 'DELETE FROM note_tags WHERE tag_id = ?',
|
||||
params: [tagId],
|
||||
@ -80,8 +75,17 @@ class Tag extends BaseItem {
|
||||
return !!r;
|
||||
}
|
||||
|
||||
static removeNote(tagId, noteId) {
|
||||
return this.db().exec('DELETE FROM note_tags WHERE tag_id = ? AND note_id = ?', [tagId, noteId]);
|
||||
static async save(o, options = null) {
|
||||
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);
|
||||
newContent.sync_time = time.unixMs();
|
||||
let options = { autoTimestamp: false };
|
||||
let options = {
|
||||
autoTimestamp: false,
|
||||
applyMetadataChanges: true,
|
||||
};
|
||||
if (action == 'createLocal') options.isNew = true;
|
||||
|
||||
if (newContent.type_ == BaseModel.MODEL_TYPE_RESOURCE && action == 'createLocal') {
|
||||
@ -321,11 +324,6 @@ class Synchronizer {
|
||||
|
||||
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);
|
||||
} else {
|
||||
this.logSyncOperation(action, local, remote, reason);
|
||||
|
Loading…
Reference in New Issue
Block a user