mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
tests for note properties
This commit is contained in:
parent
bb03a8714a
commit
a2e1fb35b8
@ -312,6 +312,84 @@ describe("Search", () => {
|
||||
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
|
||||
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("test note properties", async () => {
|
||||
const austria = note("Austria");
|
||||
|
||||
austria.relation('myself', austria.note);
|
||||
austria.label('capital', 'Vienna');
|
||||
austria.label('population', '8859000');
|
||||
|
||||
rootNote
|
||||
.child(note("Asia"))
|
||||
.child(note("Europe")
|
||||
.child(austria
|
||||
.child(note("Vienna"))
|
||||
.child(note("Sebastian Kurz"))
|
||||
)
|
||||
)
|
||||
.child(note("Mozart")
|
||||
.child(austria));
|
||||
|
||||
austria.note.type = 'text';
|
||||
austria.note.mime = 'text/html';
|
||||
austria.note.isProtected = false;
|
||||
austria.note.dateCreated = '2020-05-14 12:11:42.001+0200';
|
||||
austria.note.dateModified = '2020-05-14 13:11:42.001+0200';
|
||||
austria.note.utcDateCreated = '2020-05-14 10:11:42.001Z';
|
||||
austria.note.utcDateModified = '2020-05-14 11:11:42.001Z';
|
||||
austria.note.contentLength = 1001;
|
||||
|
||||
const parsingContext = new ParsingContext();
|
||||
|
||||
async function test(propertyName, value, expectedResultCount) {
|
||||
const searchResults = await searchService.findNotesWithQuery(`# note.${propertyName} = ${value}`, parsingContext);
|
||||
expect(searchResults.length).toEqual(expectedResultCount);
|
||||
|
||||
if (expectedResultCount === 1) {
|
||||
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
|
||||
}
|
||||
}
|
||||
|
||||
await test("type", "text", 1);
|
||||
await test("type", "code", 0);
|
||||
|
||||
await test("mime", "text/html", 1);
|
||||
await test("mime", "application/json", 0);
|
||||
|
||||
await test("isProtected", "false", 7);
|
||||
await test("isProtected", "true", 0);
|
||||
|
||||
await test("dateCreated", "'2020-05-14 12:11:42.001+0200'", 1);
|
||||
await test("dateCreated", "wrong", 0);
|
||||
|
||||
await test("dateModified", "'2020-05-14 13:11:42.001+0200'", 1);
|
||||
await test("dateModified", "wrong", 0);
|
||||
|
||||
await test("utcDateCreated", "'2020-05-14 10:11:42.001Z'", 1);
|
||||
await test("utcDateCreated", "wrong", 0);
|
||||
|
||||
await test("utcDateModified", "'2020-05-14 11:11:42.001Z'", 1);
|
||||
await test("utcDateModified", "wrong", 0);
|
||||
|
||||
await test("contentLength", "1001", 1);
|
||||
await test("contentLength", "10010", 0);
|
||||
|
||||
await test("parentCount", "2", 1);
|
||||
await test("parentCount", "3", 0);
|
||||
|
||||
await test("childrenCount", "2", 1);
|
||||
await test("childrenCount", "10", 0);
|
||||
|
||||
await test("attributeCount", "3", 1);
|
||||
await test("attributeCount", "4", 0);
|
||||
|
||||
await test("labelCount", "2", 1);
|
||||
await test("labelCount", "3", 0);
|
||||
|
||||
await test("relationCount", "1", 1);
|
||||
await test("relationCount", "2", 0);
|
||||
})
|
||||
});
|
||||
|
||||
/** @return {Note} */
|
||||
|
@ -10,6 +10,20 @@ class Note {
|
||||
this.noteId = row.noteId;
|
||||
/** @param {string} */
|
||||
this.title = row.title;
|
||||
/** @param {string} */
|
||||
this.type = row.type;
|
||||
/** @param {string} */
|
||||
this.mime = row.mime;
|
||||
/** @param {number} */
|
||||
this.contentLength = row.contentLength;
|
||||
/** @param {string} */
|
||||
this.dateCreated = row.dateCreated;
|
||||
/** @param {string} */
|
||||
this.dateModified = row.dateModified;
|
||||
/** @param {string} */
|
||||
this.utcDateCreated = row.utcDateCreated;
|
||||
/** @param {string} */
|
||||
this.utcDateModified = row.utcDateModified;
|
||||
/** @param {boolean} */
|
||||
this.isProtected = !!row.isProtected;
|
||||
/** @param {boolean} */
|
||||
@ -224,6 +238,26 @@ class Note {
|
||||
return arr.flat();
|
||||
}
|
||||
|
||||
get parentCount() {
|
||||
return this.parents.length;
|
||||
}
|
||||
|
||||
get childrenCount() {
|
||||
return this.children.length;
|
||||
}
|
||||
|
||||
get labelCount() {
|
||||
return this.attributes.filter(attr => attr.type === 'label').length;
|
||||
}
|
||||
|
||||
get relationCount() {
|
||||
return this.attributes.filter(attr => attr.type === 'relation').length;
|
||||
}
|
||||
|
||||
get attributeCount() {
|
||||
return this.attributes.length;
|
||||
}
|
||||
|
||||
/** @return {Note[]} - returns only notes which are templated, does not include their subtrees
|
||||
* in effect returns notes which are influenced by note's non-inheritable attributes */
|
||||
get templatedNotes() {
|
||||
|
@ -13,7 +13,7 @@ async function load() {
|
||||
|
||||
noteCache.reset();
|
||||
|
||||
(await sql.getRows(`SELECT noteId, title, isProtected FROM notes WHERE isDeleted = 0`, []))
|
||||
(await sql.getRows(`SELECT noteId, title, type, mime, isProtected, dateCreated, dateModified, utcDateCreated, utcDateModified, contentLength FROM notes WHERE isDeleted = 0`, []))
|
||||
.map(row => new Note(noteCache, row));
|
||||
|
||||
(await sql.getRows(`SELECT branchId, noteId, parentNoteId, prefix FROM branches WHERE isDeleted = 0`, []))
|
||||
|
@ -3,11 +3,37 @@
|
||||
const Expression = require('./expression');
|
||||
const NoteSet = require('../note_set');
|
||||
|
||||
/**
|
||||
* Search string is lower cased for case insensitive comparison. But when retrieving properties
|
||||
* we need case sensitive form so we have this translation object.
|
||||
*/
|
||||
const PROP_MAPPING = {
|
||||
"noteid": "noteId",
|
||||
"title": "title",
|
||||
"type": "type",
|
||||
"mime": "mime",
|
||||
"isprotected": "isProtected",
|
||||
"datecreated": "dateCreated",
|
||||
"datemodified": "dateModified",
|
||||
"utcdatecreated": "utcDateCreated",
|
||||
"utcdatemodified": "utcDateModified",
|
||||
"contentlength": "contentLength",
|
||||
"parentcount": "parentCount",
|
||||
"childrencount": "childrenCount",
|
||||
"attributecount": "attributeCount",
|
||||
"labelcount": "labelCount",
|
||||
"relationcount": "relationCount"
|
||||
};
|
||||
|
||||
class PropertyComparisonExp extends Expression {
|
||||
static isProperty(name) {
|
||||
return name in PROP_MAPPING;
|
||||
}
|
||||
|
||||
constructor(propertyName, comparator) {
|
||||
super();
|
||||
|
||||
this.propertyName = propertyName;
|
||||
this.propertyName = PROP_MAPPING[propertyName];
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
@ -15,8 +41,15 @@ class PropertyComparisonExp extends Expression {
|
||||
const resNoteSet = new NoteSet();
|
||||
|
||||
for (const note of inputNoteSet.notes) {
|
||||
const value = note[this.propertyName].toLowerCase();
|
||||
let value = note[this.propertyName];
|
||||
|
||||
if (value !== undefined && value !== null && typeof value !== 'string') {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (value) {
|
||||
value = value.toLowerCase();
|
||||
}
|
||||
if (this.comparator(value)) {
|
||||
resNoteSet.add(note);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ function getExpression(tokens, parsingContext) {
|
||||
return parseRelation(tokens[i]);
|
||||
}
|
||||
|
||||
if (tokens[i] === 'title') {
|
||||
if (PropertyComparisonExp.isProperty(tokens[i])) {
|
||||
const propertyName = tokens[i];
|
||||
const operator = tokens[i + 1];
|
||||
const comparedValue = tokens[i + 2];
|
||||
@ -101,6 +101,8 @@ function getExpression(tokens, parsingContext) {
|
||||
|
||||
return new PropertyComparisonExp(propertyName, comparator);
|
||||
}
|
||||
|
||||
parsingContext.addError(`Unrecognized note property "${tokens[i]}"`);
|
||||
}
|
||||
|
||||
function parseLabel(labelName) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user