Add parseSearchString to helpers

Implement parsing of a search string into terms which can be used to
match results with them.
This commit is contained in:
Hornwitser committed 2022-09-16 02:44:06 +02:00
1 parent 3b57c1e0ae
commit dfcbc559b8
2 files changed
+280

No files matched your search

+109
View File
@@ -43,4 +43,113 @@ describe("lib/helpers", function() {
), "timeout");
});
});
function parse(input, attributes) {
const result = libHelpers.parseSearchString(input, attributes);
if (!result.issues.length) {
return result.terms;
}
return result;
}
describe("parseSearchString()", function() {
function word(value, opts = {}) {
return { type: "word", value, ...opts };
}
function attr(name, value) {
return { type: "attribute", name, value: typeof value === "string" ? word(value) : value };
}
it("should split words", function() {
assert.deepEqual(parse(""), [].map(word));
assert.deepEqual(parse("word"), ["word"].map(word));
assert.deepEqual(parse("some words here"), ["some", "words", "here"].map(word));
});
it("should trim whitespace", function() {
assert.deepEqual(parse(" "), [].map(word));
assert.deepEqual(parse("word "), ["word"].map(word));
assert.deepEqual(parse(" some words here"), ["some", "words", "here"].map(word));
});
it("should parse negated words", function() {
assert.deepEqual(parse("this -that"), [word("this"), word("that", { exclude: true })]);
assert.deepEqual(parse("not-negated"), [word("not-negated")]);
});
it("should not split quoted words", function() {
assert.deepEqual(parse('"some quoted words" here'), ["some quoted words", "here"].map(word));
assert.deepEqual(parse('"a quoted string"'), ["a quoted string"].map(word));
assert.deepEqual(parse('words and "a quoted string"'), ["words", "and", "a quoted string"].map(word));
});
it("should split on quotation mark", function() {
assert.deepEqual(parse('"quoted"unquoted'), ["quoted", "unquoted"].map(word));
assert.deepEqual(parse('"quoted""double"'), ["quoted", "double"].map(word));
assert.deepEqual(parse('word"with"quote'), ["word", "with", "quote"].map(word));
assert.deepEqual(
parse('word-"with"-negation'),
[word("word-"), word("with"), word("negation", { exclude: true })]
);
});
it("should allow colons in quotes", function() {
assert.deepEqual(parse('"word:value"'), ["word:value"].map(word));
});
it("should parse attribute:value", function() {
assert.deepEqual(parse("author:Me", { author: "word" }), [attr("author", "Me")]);
assert.deepEqual(parse("word author:Me", { author: "word" }), [word("word"), attr("author", "Me")]);
assert.deepEqual(
parse("author:Me and author:You", { author: "word" }),
[attr("author", "Me"), word("and"), attr("author", "You")]
);
assert.deepEqual(
parse("author:Me"),
{
terms: [word("Me")],
issues: ['Unregonized attribute "author", use quotes to escape colons'],
}
);
assert.deepEqual(
parse("constructor:value"),
{
terms: [word("value")],
issues: ['Unregonized attribute "constructor", use quotes to escape colons'],
}
);
});
it("should throw on bad attribute format", function() {
assert.throws(
() => parse("author:Me", { author: "bad" }),
new Error("Bad attribute format bad for author")
);
});
it("should ignore attribute case", function() {
assert.deepEqual(parse("Author:Me", { author: "word" }), [attr("author", "Me")]);
assert.deepEqual(parse("AUTHOR:Me", { author: "word" }), [attr("author", "Me")]);
assert.deepEqual(parse("auThOR:Me", { author: "word" }), [attr("author", "Me")]);
});
it("should parse partial inputs", function() {
assert.deepEqual(parse("-"), [word("", { exclude: true })]);
assert.deepEqual(parse('"'), [""].map(word));
assert.deepEqual(parse('"word'), ["word"].map(word));
assert.deepEqual(parse("author:", { author: "word" }), [attr("author", "")]);
assert.deepEqual(parse("author:-", { author: "word" }), [attr("author", word("", { exclude: true }))]);
});
});
describe("wordMatches()", function() {
const match = libHelpers.wordMatches;
it("should match any inputs", function() {
assert(match(parse("word")[0], "a word in a string"), "one text");
assert(!match(parse("word")[0], "a string without"), "one text no match");
assert(match(parse("word")[0], "no match", "no things", "a word", "bad text", ""), "five text");
assert(!match(parse("unword")[0], "no match", "no things", "a word", "bad text", ""), "five text no match");
});
it("should invert match if using exclude", function() {
assert(!match(parse("-word")[0], "a word in a string"), "one text");
assert(match(parse("-word")[0], "a string without"), "one text no match");
assert(!match(parse("-word")[0], "no match", "no things", "a word", "bad text", ""), "five text");
assert(match(parse("-unword")[0], "no match", "no things", "a word", "bad text", ""), "five text no match");
});
it("should throw on bad input", function() {
assert.throws(
() => match(parse("attr:value", { attr: "word" })[0], "a string"),
new Error("wordMatches: parameter is not a word"),
);
});
});
});