diff options
| author | Mohamed Bassem <me@mbassem.com> | 2024-12-31 13:17:56 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-31 13:17:56 +0200 |
| commit | cbaf9e6034aa09911fca967b7af6cad11f154b3e (patch) | |
| tree | 6995d9d60d9ae5181af78e6577f8d7b724d7a971 /packages/shared/searchQueryParser.test.ts | |
| parent | f476fca758bb039f9605488b61ba35fc097d6cfc (diff) | |
| download | karakeep-cbaf9e6034aa09911fca967b7af6cad11f154b3e.tar.zst | |
feat: Introduce advanced search capabilities (#753)
* feat: Implement search filtering in the backend
* feat: Implement search language parser
* rename matcher name
* Add ability to interleve text
* More fixes
* be more tolerable to parsing errors
* Add a search query explainer widget
* Handle date parsing gracefully
* Fix the lockfile
* Encode query search param
* Fix table body error
* Fix error when writing quotes
Diffstat (limited to 'packages/shared/searchQueryParser.test.ts')
| -rw-r--r-- | packages/shared/searchQueryParser.test.ts | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/packages/shared/searchQueryParser.test.ts b/packages/shared/searchQueryParser.test.ts new file mode 100644 index 00000000..428d5929 --- /dev/null +++ b/packages/shared/searchQueryParser.test.ts @@ -0,0 +1,275 @@ +import { describe, expect, test } from "vitest"; + +import { parseSearchQuery } from "./searchQueryParser"; + +describe("Search Query Parser", () => { + test("simple is queries", () => { + expect(parseSearchQuery("is:archived")).toEqual({ + result: "full", + text: "", + matcher: { + type: "archived", + archived: true, + }, + }); + expect(parseSearchQuery("is:not_archived")).toEqual({ + result: "full", + text: "", + matcher: { + type: "archived", + archived: false, + }, + }); + expect(parseSearchQuery("is:fav")).toEqual({ + result: "full", + text: "", + matcher: { + type: "favourited", + favourited: true, + }, + }); + expect(parseSearchQuery("is:not_fav")).toEqual({ + result: "full", + text: "", + matcher: { + type: "favourited", + favourited: false, + }, + }); + }); + + test("simple string queries", () => { + expect(parseSearchQuery("url:https://example.com")).toEqual({ + result: "full", + text: "", + matcher: { + type: "url", + url: "https://example.com", + }, + }); + expect(parseSearchQuery('url:"https://example.com"')).toEqual({ + result: "full", + text: "", + matcher: { + type: "url", + url: "https://example.com", + }, + }); + expect(parseSearchQuery("#my-tag")).toEqual({ + result: "full", + text: "", + matcher: { + type: "tagName", + tagName: "my-tag", + }, + }); + expect(parseSearchQuery('#"my tag"')).toEqual({ + result: "full", + text: "", + matcher: { + type: "tagName", + tagName: "my tag", + }, + }); + expect(parseSearchQuery("list:my-list")).toEqual({ + result: "full", + text: "", + matcher: { + type: "listName", + listName: "my-list", + }, + }); + expect(parseSearchQuery('list:"my list"')).toEqual({ + result: "full", + text: "", + matcher: { + type: "listName", + listName: "my list", + }, + }); + }); + test("date queries", () => { + expect(parseSearchQuery("after:2023-10-12")).toEqual({ + result: "full", + text: "", + matcher: { + type: "dateAfter", + dateAfter: new Date("2023-10-12"), + }, + }); + expect(parseSearchQuery("before:2023-10-12")).toEqual({ + result: "full", + text: "", + matcher: { + type: "dateBefore", + dateBefore: new Date("2023-10-12"), + }, + }); + }); + + test("complex queries", () => { + expect(parseSearchQuery("is:fav is:archived")).toEqual({ + result: "full", + text: "", + matcher: { + type: "and", + matchers: [ + { + type: "favourited", + favourited: true, + }, + { + type: "archived", + archived: true, + }, + ], + }, + }); + + expect(parseSearchQuery("(is:fav is:archived) #my-tag")).toEqual({ + result: "full", + text: "", + matcher: { + type: "and", + matchers: [ + { + type: "favourited", + favourited: true, + }, + { + type: "archived", + archived: true, + }, + { + type: "tagName", + tagName: "my-tag", + }, + ], + }, + }); + + expect(parseSearchQuery("(is:fav is:archived) or (#my-tag)")).toEqual({ + result: "full", + text: "", + matcher: { + type: "or", + matchers: [ + { + type: "and", + matchers: [ + { + type: "favourited", + favourited: true, + }, + { + type: "archived", + archived: true, + }, + ], + }, + { + type: "tagName", + tagName: "my-tag", + }, + ], + }, + }); + + expect(parseSearchQuery("(is:fav or is:archived) and #my-tag")).toEqual({ + result: "full", + text: "", + matcher: { + type: "and", + matchers: [ + { + type: "or", + matchers: [ + { + type: "favourited", + favourited: true, + }, + { + type: "archived", + archived: true, + }, + ], + }, + { + type: "tagName", + tagName: "my-tag", + }, + ], + }, + }); + }); + test("pure text", () => { + expect(parseSearchQuery("hello")).toEqual({ + result: "full", + text: "hello", + matcher: undefined, + }); + expect(parseSearchQuery("hello world")).toEqual({ + result: "full", + text: "hello world", + matcher: undefined, + }); + }); + + test("text interlived with matchers", () => { + expect( + parseSearchQuery( + "hello is:fav world is:archived mixed world #my-tag test", + ), + ).toEqual({ + result: "full", + text: "hello world mixed world test", + matcher: { + type: "and", + matchers: [ + { + type: "favourited", + favourited: true, + }, + { + type: "archived", + archived: true, + }, + { + type: "tagName", + tagName: "my-tag", + }, + ], + }, + }); + }); + + test("unknown qualifiers are emitted as pure text", () => { + expect(parseSearchQuery("is:fav is:helloworld")).toEqual({ + result: "full", + text: "is:helloworld", + matcher: { + type: "favourited", + favourited: true, + }, + }); + }); + + test("partial results", () => { + expect(parseSearchQuery("(is:archived) or ")).toEqual({ + result: "partial", + text: "or", + matcher: { + type: "archived", + archived: true, + }, + }); + expect(parseSearchQuery("is:fav is: ( random")).toEqual({ + result: "partial", + text: "is: ( random", + matcher: { + type: "favourited", + favourited: true, + }, + }); + }); +}); |
