/* Unit tests for cache covering buildCacheKey. It also guards the documented public contract and regression-sensitive edge cases. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1311: Compass header sweep — declares the cache suite's contract for test-file scaffold coverage. */ import { describe, it, expect } from "vitest"; import { buildCacheKey } from "../changelog/core/ai-cache.ts"; const BASE = { treeHash: "abc123", files: ["src/a.ts", "src/b.ts"], diffSummary: "add login", promptHash: "prompt-hash-xyz", modelVersion: "gpt-4o", }; describe("buildCacheKey", () => { it("returns a 64-char hex string", () => { const key = buildCacheKey(BASE); expect(key).toMatch(/^[0-9a-f]{64}$/); }); it("same inputs → same key (deterministic)", () => { expect(buildCacheKey(BASE)).toBe(buildCacheKey(BASE)); }); it("files order does not affect the key", () => { const a = buildCacheKey({ ...BASE, files: ["src/a.ts", "src/b.ts"] }); const b = buildCacheKey({ ...BASE, files: ["src/b.ts", "src/a.ts"] }); expect(a).toBe(b); }); it("different files → different keys", () => { const a = buildCacheKey({ ...BASE, files: ["src/a.ts"] }); const b = buildCacheKey({ ...BASE, files: ["src/c.ts"] }); expect(a).not.toBe(b); }); it("different treeHash → different key", () => { const a = buildCacheKey({ ...BASE, treeHash: "aaa" }); const b = buildCacheKey({ ...BASE, treeHash: "bbb" }); expect(a).not.toBe(b); }); it("different diffSummary → different key", () => { const a = buildCacheKey({ ...BASE, diffSummary: "add login" }); const b = buildCacheKey({ ...BASE, diffSummary: "remove logout" }); expect(a).not.toBe(b); }); it("different promptHash → different key", () => { const a = buildCacheKey({ ...BASE, promptHash: "p1" }); const b = buildCacheKey({ ...BASE, promptHash: "p2" }); expect(a).not.toBe(b); }); it("different modelVersion → different key", () => { const a = buildCacheKey({ ...BASE, modelVersion: "gpt-4o" }); const b = buildCacheKey({ ...BASE, modelVersion: "claude-3-5-haiku-latest" }); expect(a).not.toBe(b); }); it("empty files array → stable key", () => { const key = buildCacheKey({ ...BASE, files: [] }); expect(key).toMatch(/^[0-9a-f]{64}$/); expect(key).toBe(buildCacheKey({ ...BASE, files: [] })); }); });