import { describe, expect, it } from "vite-plus/test"; import { insertRankedSearchResult, normalizeSearchQuery, scoreQueryMatch, scoreSubsequenceMatch, } from "./searchRanking.ts"; describe("normalizeSearchQuery", () => { it("trims and lowercases queries", () => { expect(normalizeSearchQuery(" UI ")).toBe("ui"); }); it("can strip leading trigger characters", () => { expect(normalizeSearchQuery(" $ui", { trimLeadingPattern: /^\$+/ })).toBe("ui"); }); }); describe("scoreQueryMatch", () => { it("prefers exact matches over broader contains matches", () => { expect( scoreQueryMatch({ value: "ui", query: "ui", exactBase: 0, prefixBase: 10, includesBase: 20, }), ).toBe(0); expect( scoreQueryMatch({ value: "building native ui", query: "ui", exactBase: 0, prefixBase: 10, boundaryBase: 20, includesBase: 30, }), ).toBeGreaterThan(0); }); it("treats boundary matches as stronger than generic contains matches", () => { const boundaryScore = scoreQueryMatch({ value: "gh-fix-ci", query: "fix", exactBase: 0, prefixBase: 10, boundaryBase: 20, includesBase: 30, boundaryMarkers: ["-"], }); const containsScore = scoreQueryMatch({ value: "highfixci", query: "fix", exactBase: 0, prefixBase: 10, boundaryBase: 20, includesBase: 30, boundaryMarkers: ["-"], }); expect(boundaryScore).not.toBeNull(); expect(containsScore).not.toBeNull(); expect(boundaryScore!).toBeLessThan(containsScore!); }); }); describe("scoreSubsequenceMatch", () => { it("scores tighter subsequences ahead of looser ones", () => { const compact = scoreSubsequenceMatch("ghfixci", "gfc"); const spread = scoreSubsequenceMatch("github-fix-ci", "gfc"); expect(compact).not.toBeNull(); expect(spread).not.toBeNull(); expect(compact!).toBeLessThan(spread!); }); }); describe("insertRankedSearchResult", () => { it("keeps the best-ranked candidates within the limit", () => { const ranked = [ { item: "b", score: 20, tieBreaker: "b" }, { item: "d", score: 40, tieBreaker: "d" }, ]; insertRankedSearchResult(ranked, { item: "a", score: 10, tieBreaker: "a" }, 2); insertRankedSearchResult(ranked, { item: "c", score: 30, tieBreaker: "c" }, 2); expect(ranked.map((entry) => entry.item)).toEqual(["a", "b"]); }); });