import { visibleWidth } from "@earendil-works/pi-tui"; import { describe, expect, it, vi } from "vitest"; import type { GoodJobRecord } from "../core.js"; import { formatLearningMarkdown, LearningListComponent } from "../ui.js"; const record: GoodJobRecord = { version: 2, id: "gj-123456789a", createdAt: "2026-01-01T00:00:00.000Z", completedAt: "2026-01-01T00:01:00.000Z", kind: "praise", feedback: "gj", source: { type: "session", cwd: "/work/shared-route", sessionPath: "/sessions/one.jsonl", sessionId: "session-1", sessionName: "Shared route", leafId: "leaf-1", agentModel: { provider: "openai", id: "worker" }, }, analysisModel: { provider: "openai", id: "worker" }, learning: { slug: "shared-route-first", summary: "Fixed the shared route", evidence: ["All focused tests passed"], behaviors: ["Inspected callers before editing"], candidateRule: "Fix the shared route before leaf callers.", }, usage: { input: 10, output: 5, cacheRead: 0, cacheWrite: 0, totalTokens: 15, cost: 0.01, }, }; describe("good-job UI", () => { it("renders slug, short ID, and labeled learning sections", () => { const markdown = formatLearningMarkdown(record); expect(markdown).toContain("## shared-route-first\nFixed the shared route"); expect(markdown).toContain("## Feedback\ngj"); expect(markdown).toContain("## Evidence\n- All focused tests passed"); expect(markdown).toContain("## Behaviors"); expect(markdown).toContain("gj-123456789a"); expect(markdown).not.toContain('"learning"'); }); it("renders imported problem records without model or usage metadata", () => { const imported: GoodJobRecord = { ...record, id: "wtf-123456789a", kind: "problem", feedback: "unexpected scope expansion", source: { type: "import", importer: "legacy-wtf-v1", fingerprint: "abc123", importedAt: "2026-01-02T00:00:00.000Z", }, analysisModel: null, usage: null, learning: { ...record.learning, slug: "avoid-scope-expansion", }, }; const markdown = formatLearningMarkdown(imported); expect(markdown).toContain("## avoid-scope-expansion"); expect(markdown).toContain("problem ยท wtf-123456789a"); expect(markdown).toContain("legacy-wtf-v1"); const done = vi.fn(); const theme = { fg: (_color: string, text: string) => text, bold: (text: string) => text, } as never; const component = new LearningListComponent( theme, [imported], { pending: 0, processing: 0, failed: 0, records: 1 }, vi.fn(), done, ); for (const character of "legacy-wtf") component.handleInput(character); expect(component.render(80).join("\n")).toContain("avoid-scope-expansion"); }); it("renders a width-safe searchable list and returns the selected id", () => { const done = vi.fn(); const requestRender = vi.fn(); const theme = { fg: (_color: string, text: string) => text, bold: (text: string) => text, } as never; const component = new LearningListComponent( theme, [record], { pending: 1, processing: 0, failed: 0, records: 1 }, requestRender, done, ); for (const character of "shared-route") component.handleInput(character); const lines = component.render(48); expect(lines.join("\n")).toContain("shared-route-first"); expect(lines.every((line) => visibleWidth(line) <= 48)).toBe(true); expect(requestRender).toHaveBeenCalled(); component.handleInput("\r"); expect(done).toHaveBeenCalledWith(record.id); }); });