/** * footer.test.ts — unit tests for the pipeline-overview footer. * * The footer is a presentation-only multi-line `belowEditor` widget: with no * UI it tracks items but writes nothing; with a stub UI it pushes a string[] * of themed lines via `ui.setWidget` (key, lines, { placement: "belowEditor" }) * and clears on `done()`. The pure {@link renderFooterList} core is asserted * directly (layout + theming); a light widget-glue test covers the wiring. */ import { describe, expect, it } from "bun:test"; import { createPipelineFooter, footerPhaseItems, footerColor, renderFooterList, FOOTER_MARKER, FOOTER_STATUS_KEY, type FooterItem, type FooterTheme, } from "../src/footer.js"; import { PHASE_LABELS } from "../src/phases.js"; import { PHASE_ANALYSIS, PHASE_FIX, PHASE_RECON } from "../src/run-state.js"; /** A fake theme that wraps text as `:` so assertions can read it. */ function fakeTheme(): FooterTheme { return { fg: (color, text) => `${color}:${text}` }; } /** Minimal UI stub capturing `setWidget` calls (key, lines, options). */ function stubUi(theme: FooterTheme = fakeTheme()): { ui: { theme: FooterTheme; setWidget: ( key: string, content: string[] | undefined, options?: { placement?: string }, ) => void; }; calls: { key: string; content: string[] | undefined; placement?: string; }[]; } { const calls: { key: string; content: string[] | undefined; placement?: string; }[] = []; return { calls, ui: { theme, setWidget(key, content, options) { calls.push({ key, content, placement: options?.placement }); }, }, }; } /** Build the canonical phase-id list a scan-only check uses. */ function scanPhaseIds(): string[] { return [PHASE_RECON, PHASE_ANALYSIS, PHASE_FIX]; } /** Items for the canonical scan-only pipeline. */ function scanItems(status: FooterItem["status"] = "pending"): FooterItem[] { return scanPhaseIds().map((id) => ({ label: PHASE_LABELS[id] ?? id, status, })); } describe("renderFooterList", () => { it("renders one bulleted, numbered, themed line per phase", () => { const lines = renderFooterList(scanItems(), -1, fakeTheme()); expect(lines).toHaveLength(3); // Each line: `• .