test/fuzzy.test.js (2209 bytes)
1 "use strict"; 2 const test = require("node:test"); 3 const assert = require("node:assert/strict"); 4 const fc = require("fast-check"); 5 const Fuzzy = require("../lib/fuzzy.js"); 6 7 const text = fc.stringMatching(/^[a-z ]{0,30}$/); 8 9 test("every subsequence of a text matches it", () => { 10 fc.assert(fc.property(text, fc.array(fc.boolean(), { maxLength: 30 }), (t, keep) => { 11 const word = [...t.replace(/ /g, "")].filter((_, i) => keep[i]).join(""); 12 assert.notEqual(Fuzzy.score(word, t), null); 13 }), { numRuns: 1000 }); 14 }); 15 16 test("a letter that the text lacks gives no match", () => { 17 fc.assert(fc.property(text, (t) => { 18 const missing = [..."abcdefghijklmnopqrstuvwxyz"].find((c) => !t.includes(c)); 19 if (missing) assert.equal(Fuzzy.score(missing, t), null); 20 }), { numRuns: 1000 }); 21 }); 22 23 test("every word of the query must match", () => { 24 fc.assert(fc.property(text, text, (a, b) => { 25 const both = Fuzzy.score(a + " " + b, "x"); 26 if (Fuzzy.score(a, "x") === null || Fuzzy.score(b, "x") === null) assert.equal(both, null); 27 }), { numRuns: 1000 }); 28 }); 29 30 test("case does not matter", () => { 31 fc.assert(fc.property(text, text, (q, t) => { 32 assert.equal(Fuzzy.score(q.toUpperCase(), t), Fuzzy.score(q, t.toUpperCase())); 33 }), { numRuns: 1000 }); 34 }); 35 36 test("filter keeps exactly the items that match", () => { 37 fc.assert(fc.property(fc.array(text, { maxLength: 20 }), text, (items, q) => { 38 const got = Fuzzy.filter(items, q, (x) => x); 39 const want = q.trim() === "" ? items : items.filter((x) => Fuzzy.score(q, x) !== null); 40 assert.deepEqual([...got].sort(), [...want].sort()); 41 }), { numRuns: 1000 }); 42 }); 43 44 test("a blank query keeps the order", () => { 45 assert.deepEqual(Fuzzy.filter(["b", "a"], " ", (x) => x), ["b", "a"]); 46 }); 47 48 test("a whole word ranks above scattered letters", () => { 49 assert.deepEqual(Fuzzy.filter(["d w m x", "dwm"], "dwm", (x) => x), ["dwm", "d w m x"]); 50 }); 51 52 test("the start of a word ranks above the inside of a word", () => { 53 assert.deepEqual(Fuzzy.filter(["xwiki", "wiki x"], "wiki", (x) => x), ["wiki x", "xwiki"]); 54 }); 55 56 test("Japanese text matches", () => { 57 assert.notEqual(Fuzzy.score("辞書", "Jisho: 日本語の辞書"), null); 58 });