import { describe, it, expect } from "vitest"; import { fuzzyScore, fuzzyMatch, fuzzySort } from "./fuzzy.js"; describe("fuzzyScore", () => { it("matches an empty query as no-match (score 0)", () => { expect(fuzzyScore("", "mara").score).toBe(0); }); it("matches a whole-string query at score 1", () => { const r = fuzzyScore("mara", "Mara"); expect(r.score).toBe(1); expect(r.indices).toEqual([0, 1, 2, 3]); }); it("matches a subsequence in order", () => { const r = fuzzyScore("mr", "Mara"); expect(r.score).toBeGreaterThan(0); expect(r.indices).toEqual([0, 2]); }); it("does not match a non-subsequence", () => { expect(fuzzyScore("z", "Mara").score).toBe(0); expect(fuzzyScore("marz", "Mara").score).toBe(0); }); it("scores consecutive matches higher than scattered ones", () => { const consecutive = fuzzyScore("mar", "maria").score; const scattered = fuzzyScore("mr", "maria").score; expect(consecutive).toBeGreaterThan(scattered); }); it("scores word-start matches higher", () => { const wordStart = fuzzyScore("h", "harbor").score; const mid = fuzzyScore("r", "harbor").score; expect(wordStart).toBeGreaterThan(mid); }); }); describe("fuzzyMatch", () => { it("is true for a subsequence and false otherwise", () => { expect(fuzzyMatch("mr", "Mara")).toBe(true); expect(fuzzyMatch("z", "Mara")).toBe(false); }); }); describe("fuzzySort", () => { const items = [ { id: "ada", name: "Ada Lovelace" }, { id: "maria", name: "Maria Harbor" }, { id: "mark", name: "Mark Twain" }, ]; it("returns all items for an empty query, preserving order", () => { expect(fuzzySort(items, "", (i) => i.name).map((i) => i.id)).toEqual(["ada", "maria", "mark"]); }); it("drops non-matches and orders by descending score", () => { const sorted = fuzzySort(items, "mar", (i) => i.name); expect(sorted.map((i) => i.id)).toContain("maria"); expect(sorted.map((i) => i.id)).not.toContain("ada"); // "Maria Harbor" (word start) should beat "Mark Twain" (word start) only on tie-break; both match. expect(sorted.length).toBe(2); }); it("is stable for equal scores", () => { // "ada" and "amy" both score 2 for query "a" (word-start match); input // order must be preserved. const stable = [ { id: "a", name: "ada" }, { id: "b", name: "amy" }, ]; const sorted = fuzzySort(stable, "a", (i) => i.name); expect(sorted.map((i) => i.id)).toEqual(["a", "b"]); }); });