/* Unit tests for search route covering RFC-1115 AC-1: flattened citation SearchResult; RFC-1115 AC-2: tookMs is measured, not hardcoded. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1115: initial search-route tests. */ import { describe, it, expect } from "vitest"; import { runAgentSearch, type AgentSearchPorts } from "../search-route.ts"; import type { SearchChunk, SearchManifest } from "@warpgogol/werkstatt-shared/agent"; const chunk: SearchChunk = { id: "de:/about:page", url: "/about", lang: "de", type: "page", blockId: null, heading: "Über uns", text: "About the company", title: "Über uns", canonicalUrl: "https://example.example/about", updatedAt: "2026-08-20", }; const manifest: SearchManifest = { schema: "2", site: "s", model: "@cf/baai/bge-m3", dimensions: 1024, generatedAt: "2026-09-19T00:00:00Z", contentHash: "sha256:test", chunks: [chunk], }; function makePorts(matches: Array<{ id: string; score: number }>): AgentSearchPorts { return { ai: { async run() { return { data: [[0.1, 0.2, 0.3]] }; }, }, searchIndex: { async query() { return { matches }; }, }, }; } describe("RFC-1115 AC-1: flattened citation SearchResult", () => { it("emits title/canonicalUrl/updatedAt/lang/type/score/text — no nested chunk", async () => { const res = await runAgentSearch( { q: "about", topK: 5 }, manifest, makePorts([{ id: chunk.id, score: 0.87 }]), ); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual({ title: "Über uns", canonicalUrl: "https://example.example/about", updatedAt: "2026-08-20", lang: "de", type: "page", score: 0.87, text: "About the company", }); expect("chunk" in res.results[0]).toBe(false); }); it("skips matches whose chunk id is absent from the manifest", async () => { const res = await runAgentSearch( { q: "about", topK: 5 }, manifest, makePorts([ { id: "missing", score: 0.99 }, { id: chunk.id, score: 0.5 }, ]), ); expect(res.results).toHaveLength(1); expect(res.results[0].score).toBe(0.5); }); it("returns empty results when the index has no matches", async () => { const res = await runAgentSearch({ q: "about", topK: 5 }, manifest, makePorts([])); expect(res.results).toEqual([]); expect(res.query).toBe("about"); }); }); describe("RFC-1115 AC-2: tookMs is measured, not hardcoded", () => { it("tookMs equals elapsed time from the injected clock", async () => { let tick = 1000; const res = await runAgentSearch( { q: "about", topK: 5 }, manifest, makePorts([{ id: chunk.id, score: 0.9 }]), () => (tick += 25), ); // two now() calls: start + end → 25ms elapsed expect(res.tookMs).toBe(25); }); it("tookMs is a non-negative number with the real clock", async () => { const res = await runAgentSearch({ q: "about", topK: 5 }, manifest, makePorts([])); expect(typeof res.tookMs).toBe("number"); expect(res.tookMs).toBeGreaterThanOrEqual(0); }); });