import assert from "node:assert/strict"; import { test } from "node:test"; import { FakeDocument, FakeElement } from "./fake-dom.ts"; import { renderCockpit } from "./render.ts"; import { type CockpitView, cockpitView } from "./view.ts"; function view(): CockpitView { return cockpitView({ status: "red", missing: ["planning.plan#blue"], networks: [ { network: "ci", tokens: [{ token: "ci.build", supply: 2, instances: ["ci-a", "ci-b"], satisfied: true }], missing: [], }, { network: "planning", tokens: [ { token: "planning.plan#blue", supply: 0, instances: [], satisfied: false }, { token: "planning.plan#red", supply: 1, instances: ["plan-a"], satisfied: true }, ], missing: ["planning.plan#blue"], }, ], diversity: { status: "green", roles: [] }, nonAgentic: ["send-email"], }); } test("renders one section per network with a demand×supply row per token", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); renderCockpit(host, doc, view()); const networks = host.byClass("cockpit-network"); assert.deepEqual( networks.map((n) => n.getAttribute("data-network")), ["ci", "planning"], ); const tokens = host.byClass("cockpit-token"); assert.deepEqual( tokens.map((t) => t.getAttribute("data-token")), ["ci.build", "planning.plan#blue", "planning.plan#red"], ); }); test("token tables use valid / structure (rows are never direct children)", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); renderCockpit(host, doc, view()); const tables = host.byClass("cockpit-tokens"); assert.ok(tables.length >= 1, "at least one token table is rendered"); for (const table of tables) { // A
must only contain section elements (/), never a bare . assert.deepEqual( table.children.map((c) => c.tagName), ["thead", "tbody"], "table children are the section wrappers, not rows", ); const [thead, tbody] = table.children; assert.deepEqual( thead?.children.map((c) => c.tagName), ["tr"], "the header row lives inside ", ); for (const row of tbody?.children ?? []) { assert.equal(row.tagName, "tr", "every data row lives inside "); } } }); test("a missing agent type renders a RED token, a RED network and a red missing light", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); renderCockpit(host, doc, view()); const missingTok = host.byData("token", "planning.plan#blue")[0]; assert.equal(missingTok?.getAttribute("data-status"), "red"); const planning = host.byData("network", "planning")[0]; assert.equal(planning?.getAttribute("data-status"), "red"); const lights = host.byClass("cockpit-light").filter((l) => l.getAttribute("data-light-id")?.startsWith("missing:")); assert.equal(lights.length, 1); assert.equal(lights[0]?.getAttribute("data-status"), "red"); assert.match(lights[0]?.text() ?? "", /planning\.plan#blue/); }); test("the overall status and diversity light render in the header", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); renderCockpit(host, doc, view()); assert.equal(host.byClass("cockpit")[0]?.getAttribute("data-status"), "red"); const badge = host.byData("badge-id", "overall")[0]; assert.equal(badge?.getAttribute("data-status"), "red"); const diversity = host.byData("light-id", "diversity")[0]; assert.equal(diversity?.getAttribute("data-status"), "green"); }); test("clicking a worker chip drills into that instance's relay stream", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); const drilled: string[] = []; renderCockpit(host, doc, view(), { onDrill: (stream) => drilled.push(stream) }); const chip = host.byData("stream", "ci-a")[0]; assert.ok(chip instanceof FakeElement); chip.dispatch("click"); assert.deepEqual(drilled, ["ci-a"]); }); test("re-rendering replaces prior content (idempotent refresh)", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); renderCockpit(host, doc, view()); renderCockpit(host, doc, view()); assert.equal(host.children.length, 1, "host holds exactly one cockpit root after re-render"); assert.equal(host.byClass("cockpit-network").length, 2); }); test("embedded and standalone render identically — same view, same host subset ⇒ same DOM", () => { const doc = new FakeDocument(); const standaloneHost = new FakeElement("body"); const embeddedHost = new FakeElement("div"); const v = view(); renderCockpit(standaloneHost, doc, v); renderCockpit(embeddedHost, doc, v); const shape = (root: FakeElement): unknown => ({ tag: root.tagName, cls: root.className, attrs: [...root.attributes.entries()].sort(), text: root.textContent, children: root.children.map(shape), }); const standaloneRoot = standaloneHost.children[0]; const embeddedRoot = embeddedHost.children[0]; assert.ok(standaloneRoot !== undefined && embeddedRoot !== undefined); assert.deepEqual(shape(standaloneRoot), shape(embeddedRoot)); }); test("non-agentic task types render in a footer", () => { const doc = new FakeDocument(); const host = new FakeElement("body"); renderCockpit(host, doc, view()); assert.match(host.byClass("cockpit-nonagentic")[0]?.text() ?? "", /send-email/); });