import { expect, test } from "bun:test"; import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { EvidencePopover } from "./evidence-popover"; import type { EvidenceRow } from "./evidence"; const ROWS: EvidenceRow[] = [ { optionId: "github", label: "GitHub Apps", origin: "chat", supporters: ["mina", "jules"], opposers: ["lee"], items: [{ id: "r1", kind: "reason", text: "People already have GitHub accounts.", sources: [{ messageId: "m1", author: { kind: "member", handle: "mina" }, quote: "People already have GitHub accounts.", start: 0, end: 36, role: "reason", }], }], }, { optionId: "sso", label: "Enterprise SSO", origin: "planner", supporters: [], opposers: [], items: [], rationale: "Enterprise customers expect SAML.", }, ]; test("each row shows its label, stances, sourced evidence and Planner rationale", () => { let markup = renderToStaticMarkup( createElement(EvidencePopover, { rows: ROWS, onSource: () => {} }), ); expect(markup).toContain('aria-label="Evidence"'); expect(markup).toContain("GitHub Apps"); expect(markup).toContain("Supported by mina, jules"); expect(markup).toContain("Opposed by lee"); expect(markup).toContain("ring-2 ring-destructive"); expect(markup).toContain("People already have GitHub accounts."); expect(markup).toContain('aria-label="Show “People already have GitHub accounts.” in chat"'); expect(markup).toContain("Planner suggested"); expect(markup).toContain("Why Chopin suggested this: Enterprise customers expect SAML."); expect(markup).not.toMatch(/<(input|select|textarea)\b/); }); test("shows at most eight avatar images while naming every participant accessibly", () => { let handles = ["mina", "jules", "lee", "ana", "bo", "cy", "di", "eve", "flo", "gus"]; let opponents = ["nora", "otto", "paz", "quinn", "ravi", "suki", "tali", "uma", "viktor"]; let row: EvidenceRow = { optionId: "many", label: "A crowded option", origin: "chat", supporters: handles, opposers: opponents, items: [], }; let markup = renderToStaticMarkup( createElement(EvidencePopover, { rows: [row], onSource: () => {} }), ); expect(markup.match(/+2"); expect(markup).toContain(">+1"); }); test("omits source controls without sources and hides non-Planner rationale", () => { let row: EvidenceRow = { optionId: "human", label: "Human option", origin: "human", supporters: [], opposers: [], items: [{ id: "c1", kind: "constraint", text: "Must work offline.", sources: [], }], rationale: "Only a Planner rationale belongs here.", }; let markup = renderToStaticMarkup( createElement(EvidencePopover, { rows: [row], onSource: () => {} }), ); expect(markup).toContain("Constraint"); expect(markup).toContain("Must work offline."); expect(markup).not.toContain("Show “Must work offline.” in chat"); expect(markup).not.toContain("Why Chopin suggested this:"); }); test("shows an exact attributed quote for a sourced Planner option", () => { let row: EvidenceRow = { optionId: "jev", label: "Invite Jev", origin: "planner", supporters: [], opposers: [], items: [], rationale: "Jev can review the plan.", source: { messageId: "m-jevi", author: { kind: "member", handle: "mina" }, quote: "Jev needs access to the release plan.", start: 4, end: 41, role: "option", }, }; let markup = renderToStaticMarkup( createElement(EvidencePopover, { rows: [row], onSource: () => {} }), ); expect(markup).toContain("Invite Jev"); expect(markup).toContain("@mina"); expect(markup).toContain(" { let row: EvidenceRow = { optionId: "jev", label: "Invite Jev", origin: "planner", supporters: [], opposers: [], items: [], rationale: "Repository permissions require it.", }; let markup = renderToStaticMarkup( createElement(EvidencePopover, { rows: [row], onSource: () => {} }), ); expect(markup).toContain("Why Chopin suggested this: Repository permissions require it."); expect(markup).not.toContain("