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("