// @vitest-environment happy-dom import { beforeAll, describe, expect, it } from "vitest"; import { renderSidebar } from "./catalog.js"; import type { CatalogListener, CatalogStore } from "./events.js"; import type { InTheWay, Session } from "./types.js"; // happy-dom runs without a backing store; renderSidebar reads the persisted // sidebar width on mount. beforeAll(() => { Object.defineProperty(window, "localStorage", { value: { getItem: () => null, setItem: () => {} }, }); // No daemon here; renderSidebar treats a failed info fetch as "absolute // paths are a fine fallback". window.fetch = () => Promise.reject(new Error("offline")); }); function session(overrides: Partial): Session { return { id: "11111111-2222-3333-4444-555555555555", cwd: "/home/naps/tea/maestro", command: "claude", env: {}, metadata: {}, status: "Running", created_at: "2026-08-24T10:00:00Z", ...overrides, }; } function storeWith(sessions: Session[]): CatalogStore { const state = { sessions: new Map(sessions.map((s) => [s.id, s])) }; return { snapshot: () => state, // Like the real store, deliver an immediate snapshot so the sidebar // renders its rows during construction. subscribe: (fn: CatalogListener) => { fn(state); return () => {}; }, } as unknown as CatalogStore; } function rowFor(el: HTMLElement, id: string): HTMLElement | null { return el.querySelector(`[data-session-id="${id}"]`); } describe("blocked-work indicator (#83)", () => { it("marks the row of a blocked session with the shared phrasing", () => { const blocked = session({ id: "aaaaaaaa-0000-0000-0000-000000000001", blocked_work: { uncommitted_files: 3, unpushed_commits: 2 }, }); const el = renderSidebar(storeWith([blocked])).el; const badge = rowFor(el, blocked.id)?.querySelector(".leaf-blocked"); expect(badge?.textContent).toContain("⚠"); expect(badge?.textContent).toContain("3 uncommitted files, 2 unpushed commits"); }); it("does not mark clear or unprobed sessions", () => { const clear = session({ id: "aaaaaaaa-0000-0000-0000-000000000002", blocked_work: {} as InTheWay, }); const unprobed = session({ id: "aaaaaaaa-0000-0000-0000-000000000003", }); const el = renderSidebar(storeWith([clear, unprobed])).el; expect(rowFor(el, clear.id)?.querySelector(".leaf-blocked")).toBeNull(); expect(rowFor(el, unprobed.id)?.querySelector(".leaf-blocked")).toBeNull(); }); it("restates the warning at the kill confirm", async () => { const confirmations: string[] = []; window.confirm = (msg?: string) => { confirmations.push(msg ?? ""); return false; }; const blocked = session({ id: "aaaaaaaa-0000-0000-0000-000000000004", command: "bash", blocked_work: { untracked_files: 1 }, }); const el = renderSidebar(storeWith([blocked])).el; const kill = rowFor(el, blocked.id)?.querySelector(".leaf-kill"); kill?.click(); await Promise.resolve(); expect(confirmations).toHaveLength(1); expect(confirmations[0]).toContain("1 untracked file"); expect(confirmations[0]).toContain("refused unless forced"); }); it("confirms plainly when nothing blocks", async () => { const confirmations: string[] = []; window.confirm = (msg?: string) => { confirmations.push(msg ?? ""); return false; }; const plain = session({ id: "aaaaaaaa-0000-0000-0000-000000000005" }); const el = renderSidebar(storeWith([plain])).el; rowFor(el, plain.id)?.querySelector(".leaf-kill")?.click(); await Promise.resolve(); expect(confirmations).toEqual(['Kill session "claude"?']); }); });