SPB Git

spb/khaelor Public

KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.

TypeScript 82.9% HTML 14.9% CSS 1.1% JavaScript 0.7%
2.4 KB · 67 lines typescript
Raw Blame History
1/**2 * KHAELOR3 * File: tests/tui/fuzzy.test.ts4 * Description: Fuzzy matcher tests — subsequence matching, ranking bonuses, stability, matched indices.5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import { describe, expect, it } from "vitest";11import { fuzzyFilter, fuzzyMatch } from "../../src/tui/composer/fuzzy.js";1213describe("fuzzyMatch", () => {14  it("matches subsequences case-insensitively", () => {15    expect(fuzzyMatch("agt", "src/kernel/Agent.ts")).not.toBeNull();16    expect(fuzzyMatch("zzz", "src/kernel/agent.ts")).toBeNull();17  });1819  it("returns matched indices for underlining", () => {20    const m = fuzzyMatch("se", "sessions");21    expect(m?.indices).toEqual([0, 1]);22  });2324  it("empty query matches everything with score 0", () => {25    expect(fuzzyMatch("", "anything")).toEqual({ score: 0, indices: [] });26  });2728  it("exact prefix outranks a scattered match", () => {29    const prefix = fuzzyMatch("diff", "diff viewer") as { score: number };30    const scattered = fuzzyMatch("diff", "docs/if_frame.ts") as { score: number };31    expect(prefix.score).toBeGreaterThan(scattered.score);32  });3334  it("boundary matches outrank mid-word matches", () => {35    const boundary = fuzzyMatch("ag", "src/agent.ts") as { score: number };36    const midWord = fuzzyMatch("ag", "src/flagpole.ts") as { score: number };37    expect(boundary.score).toBeGreaterThan(midWord.score);38  });39});4041describe("fuzzyFilter", () => {42  const items = ["src/kernel/agent.ts", "src/agents/agent-runtime.ts", "tests/agent.test.ts"];4344  it("excludes non-matches and ranks by score", () => {45    const ranked = fuzzyFilter("agent", items, (s) => s);46    expect(ranked.length).toBe(3);47    expect(ranked.every((r) => r.score > 0)).toBe(true);48  });4950  it("shorter target wins ties (length penalty)", () => {51    const ranked = fuzzyFilter("cost", ["/cost-explorer", "/cost"], (s) => s);52    expect(ranked[0]?.item).toBe("/cost");53  });5455  it("keeps provider order for equal scores (stable)", () => {56    const ranked = fuzzyFilter("", items, (s) => s);57    expect(ranked.map((r) => r.item)).toEqual(items);58  });5960  it("filters slash commands by fragment", () => {61    const cmds = ["/sessions", "/new", "/resume", "/cost"];62    const ranked = fuzzyFilter("se", cmds, (s) => s);63    expect(ranked.map((r) => r.item)).toContain("/sessions");64    expect(ranked.map((r) => r.item)).not.toContain("/cost");65  });66});67