import assert from "node:assert/strict"; import test from "node:test"; import { groupCampaignValidationIssues } from "../src/features/campaigns/review/validationIssueGroups.ts"; const cause = { code: "missing_required_attachment", severity: "warning", path: "/entries/recipient-1/attachments/0", message: "No file matched filter" }; const outcome = { code: "missing_attachment_coverage", severity: "info", path: "/entries/recipient-1", message: "Policy excludes this message without attachments" }; test("one grouped condition preserves the missing-rule cause and policy outcome regardless of order", () => { for (const records of [[cause, outcome], [outcome, cause]]) { const groups = groupCampaignValidationIssues(records); assert.equal(groups.length, 1); assert.deepEqual(groups[0].causes, [cause]); assert.deepEqual(groups[0].outcomes, [outcome]); assert.deepEqual(groups[0].evidence, records); assert.equal(groups[0].severity, "warning"); } }); test("different recipients, unmatched rule without coverage, and unrelated errors are never collapsed", () => { const email = { code: "missing_email", severity: "error", path: "/entries/recipient-1", message: "No address" }; const other = { ...cause, path: "/entries/recipient-2/attachments/0" }; const groups = groupCampaignValidationIssues([cause, outcome, email, other]); assert.equal(groups.length, 3); assert.deepEqual(groups[1].evidence, [email]); assert.deepEqual(groups[2].evidence, [other]); }); test("multiple rule causes remain visible and a real block is not downgraded by an informational outcome", () => { const blocked = { ...cause, severity: "error", path: "/entries/recipient-1/attachments/1" }; const [group] = groupCampaignValidationIssues([cause, blocked, outcome]); assert.equal(group.severity, "error"); assert.equal(group.causes.length, 2); assert.equal(group.evidence.length, 3); });