src/features/reports/report-data.test.ts
Linked repository file from this build.
import { reportRowFromReview } from "@/features/reports/report-input";
import { expect, test } from "bun:test";
import { generateSeedBatch } from "@/programs/snap-negative/seed-generator";
import type { SnapReview } from "@/programs/snap-negative/types";
import {
aggregateReport as aggregateRows,
countyLabel,
currentFfyFilters,
examinerLabel,
reportCsv,
type ReportCounts,
} from "./report-data";
test("default report bounds follow the October rollover in Pennsylvania time", () => {
for (const date of ["2026-01-01T00:00:00Z", "2026-09-13T12:00:00Z", "2026-10-01T03:59:59Z"])
expect(currentFfyFilters(new Date(date))).toEqual({ from: "2025-10", through: "2026-09" });
expect(currentFfyFilters(new Date("2026-10-01T04:00:00Z"))).toEqual({
from: "2026-10",
through: "2027-09",
});
});
const generated = generateSeedBatch({
ffyFrom: 2026,
ffyTo: 2026,
perMonth: 5,
seed: 11,
asOf: new Date("2026-09-08T12:00:00Z"),
preserveReviewNumbers: [],
}).reviews;
function released(outcome: "clean" | "error") {
const review = generated.find(
(row) => row.state === "released_to_reporting" && row.outcome === outcome,
);
if (!review) throw new Error(`Missing released ${outcome} fixture.`);
return {
...structuredClone(review),
state: "released_to_reporting" as const,
errorSummaryReleased: {
actor: { name: "Manager", role: "program_manager" as const },
at: "2026-09-13T12:00:00Z",
},
};
}
function fixtures(): SnapReview[] {
const clean = { ...released("clean"), sampleMonth: "2026-04", examiner: "101", county: "02" };
const error = { ...released("error"), sampleMonth: "2026-07", examiner: "102", county: "01" };
const stale: SnapReview = structuredClone(clean);
stale.state = "awaiting_cao_response";
delete stale.errorSummaryReleased;
const open: SnapReview = structuredClone(error);
open.state = "awaiting_cao_response";
delete open.errorSummaryReleased;
open.validation!.findings = [
{ id: "finding", code: "test", field: "finding", message: "Open finding" },
];
const dropped: SnapReview = {
...structuredClone(error),
state: "dropped",
outcome: "drop",
sampleMonth: "2026-08",
};
const active: SnapReview = {
...structuredClone(clean),
state: "new_active",
outcome: "",
sampleMonth: "2026-03",
};
return [clean, error, stale, open, dropped, active];
}
test("report dimensions reconcile and error summary counts use the release flag", () => {
const reviews = fixtures();
const before = structuredClone(reviews);
const summary = aggregateReport(reviews);
expect(summary).toMatchObject({
total: 6,
approved: 2,
completed: 3,
clean: 1,
error: 1,
eligible: 2,
ineligibleApproved: 2,
});
for (const groups of [summary.byState, summary.byMonth, summary.byExaminer, summary.byCounty]) {
for (const key of [
"total",
"approved",
"completed",
"clean",
"error",
"eligible",
"ineligibleApproved",
] as (keyof ReportCounts)[])
expect(groups.reduce((sum, group) => sum + group[key], 0)).toBe(summary[key]);
}
expect(summary.byState.find((group) => group.key === "awaiting_review")?.total).toBe(0);
expect(summary.byCounty.map((group) => group.label)).toEqual(["Adams", "Allegheny"]);
expect(reviews).toEqual(before);
});
test("sample-month boundaries are inclusive and combine with county and examiner", () => {
const rows = fixtures();
const summary = aggregateReport(rows, { from: "2026-04", through: "2026-07" });
expect(summary.total).toBe(4);
expect(summary.byMonth.map((group) => group.key)).toEqual(["2026-04", "2026-07"]);
expect(
aggregateReport(rows, { from: "2026-04", through: "2026-07", examiner: "101", county: "02" }),
).toMatchObject({ total: 2, clean: 1, error: 0, ineligibleApproved: 1 });
expect(aggregateReport(rows, { examiner: "101", county: "01" }).total).toBe(0);
expect(aggregateReport([], {})).toMatchObject({
total: 0,
completed: 0,
eligible: 0,
byMonth: [],
byExaminer: [],
byCounty: [],
});
});
test("internal CSV records filters, all group counts, and escapes untrusted labels", () => {
const review = released("clean");
review.examiner = 'Unknown, "staff"\nsecond line';
review.county = '=HYPERLINK("example")';
const filters = {
examiner: review.examiner,
county: review.county,
from: "2025-10",
through: "2026-09",
};
const summary = aggregateReport([review], filters);
const csv = reportCsv(summary, filters, "2026-09-09T12:00:00Z");
expect(csv).toContain("Program Error Summary");
expect(csv).toContain("2026-09-09T12:00:00Z");
expect(csv).toContain("Sample month from,2025-10");
expect(csv).toContain('"Unknown, ""staff""\nsecond line"');
expect(csv).toContain('"\'=HYPERLINK(""example"")"');
for (const section of ["Workflow state", "Sample month", "Examiner", "County"])
expect(csv).toContain(`${section},`);
expect(csv).toContain("Summary,all,All matching reviews,1,1,1,1,0,1,0");
expect(countyLabel("02")).toBe("Allegheny");
expect(examinerLabel("101")).toBe("Alex Examiner");
});
test("error summary uses one historic pair and retains uncoded errors", () => {
const first = released("error");
first.facts.answers.variances = [
{ element: "416", nature: "096" },
{ element: "416", nature: "096" },
{ element: "540", nature: "096" },
];
const missing = structuredClone(first);
missing.facts.answers.variances = [];
const stale: SnapReview = structuredClone(first);
stale.state = "awaiting_cao_response";
delete stale.errorSummaryReleased;
const clean = released("clean");
clean.facts.answers.variances = first.facts.answers.variances;
const summary = aggregateReport([first, missing, stale, clean]);
expect(summary.error).toBe(2);
expect(
summary.byErrorCode.map(({ element, nature, reviews }) => ({ element, nature, reviews })),
).toEqual([
{ element: "", nature: "", reviews: 1 },
{ element: "416", nature: "096", reviews: 1 },
]);
expect(summary.byErrorCode[1].elementLabel).toBe("Action Type");
expect(summary.byErrorCode[1].natureLabel).toBe("Policy incorrectly applied");
expect(aggregateReport([first], { examiner: "nonexistent" }).byErrorCode).toEqual([]);
const csv = reportCsv(summary, {}, "2026-09-09T12:00:00Z");
expect(csv).toContain("Element code,Nature code");
expect(csv).toContain(
"Error summary codes,416/096,Action Type · Policy incorrectly applied,1,1,1,0,1,1,0,416,096",
);
});
function aggregateReport(reviews: Parameters<typeof reportRowFromReview>[0][], filters = {}) {
return aggregateRows(reviews.map(reportRowFromReview), filters);
}