import { describe, expect, it } from "vitest"; import { fuzzy, pieces, rank } from "../src/lib/fuzzy"; describe("fuzzy", () => { it("matches a subsequence, not just a substring", () => { expect(fuzzy("wsr", "website redesign")).not.toBeNull(); expect(fuzzy("zzz", "website redesign")).toBeNull(); }); it("is case insensitive and ignores surrounding space in the query", () => { expect(fuzzy(" WEB ", "website")).not.toBeNull(); }); it("returns every match for an empty query", () => { expect(fuzzy("", "anything")).toEqual({ score: 0, ranges: [] }); }); it("merges adjacent letters into one range", () => { expect(fuzzy("web", "website")?.ranges).toEqual([[0, 3]]); }); it("keeps separate runs apart", () => { expect(fuzzy("wr", "website redesign")?.ranges).toEqual([ [0, 1], [8, 9], ]); }); it("scores a word start above a letter buried mid-word", () => { const start = fuzzy("r", "website redesign")?.score ?? 0; const buried = fuzzy("b", "website redesign")?.score ?? 0; expect(start).toBeGreaterThan(buried); }); }); describe("rank", () => { const items = ["web", "website redesign", "errands", "someday"]; const label = (item: string): string => item; it("keeps the given order when nothing is typed", () => { expect(rank("", items, label).map((hit) => hit.item)).toEqual(items); }); it("puts the shorter exact head first", () => { expect(rank("web", items, label)[0].item).toBe("web"); }); it("drops what does not match at all", () => { expect(rank("qq", items, label)).toEqual([]); }); it("breaks ties by the incoming order", () => { expect(rank("e", ["ea", "eb"], label).map((hit) => hit.item)).toEqual([ "ea", "eb", ]); }); }); describe("pieces", () => { it("splits a label into matched and unmatched runs", () => { expect(pieces("website", [[0, 3]])).toEqual([ { text: "web", hit: true }, { text: "site", hit: false }, ]); }); it("returns the whole label when nothing matched", () => { expect(pieces("website", [])).toEqual([{ text: "website", hit: false }]); }); it("rebuilds the original text exactly", () => { const hit = fuzzy("wr", "website redesign"); const parts = pieces("website redesign", hit?.ranges ?? []); expect(parts.map((part) => part.text).join("")).toBe("website redesign"); }); });