import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import { readFileSync } from "node:fs"; const api = readFileSync("src/api/campaigns.ts", "utf8"); const page = readFileSync("src/features/reports/AggregateReportsPage.tsx", "utf8"); const reportPage = readFileSync("src/features/campaigns/CampaignReportPage.tsx", "utf8"); const reviewPage = readFileSync("src/features/campaigns/ReviewSendPage.tsx", "utf8"); const operatorPage = readFileSync("src/features/operator/OperatorQueuePage.tsx", "utf8"); const deliveryMode = readFileSync("src/features/campaigns/utils/deliveryMode.ts", "utf8"); const translationCatalog = readFileSync("src/i18n/generatedTranslations.ts", "utf8"); assert(api.includes('"/api/v1/campaigns/aggregate-reports"'), "the report list uses the safe aggregate collection"); assert(api.includes("/api/v1/campaigns/aggregate-reports/${encodeURIComponent(campaignId)}"), "the selected report uses the safe aggregate projection"); assert(page.includes("listAggregateReportCampaigns"), "the page loads only the safe Campaign selector projection"); assert(page.includes("getAggregateCampaignReport"), "the page loads only the safe aggregate report projection"); assert(!page.includes("getCampaignReport"), "the aggregate page cannot load the recipient-aware full report"); assert(!page.includes("getCampaignJobs"), "the aggregate page cannot cache recipient jobs"); assert(!page.includes("getCampaignJobDetail"), "the aggregate page has no detail route"); assert(!page.includes("downloadCampaignJobsCsv"), "the aggregate page has no export path"); assert(!page.includes("localStorage"), "the aggregate page does not persist report data in local storage"); assert(!page.includes("sessionStorage"), "the aggregate page does not persist report data in session storage"); assert(page.includes("TableActionGroup"), "campaign selection uses the central icon-only table action group"); assert(page.includes("disabled: campaign.id === selectedFromUrl"), "the selected row action stays visible and disabled"); assert(!page.includes("{report.population.denominator_definition}"), "the known denominator contract uses a localized UI explanation"); assert(!page.includes("{report.privacy.rule}"), "the known privacy contract uses a localized UI explanation"); assert(page.includes("all_persisted_recipient_delivery_jobs_for_the_se.208e90cc"), "the denominator explanation is bilingual"); assert(page.includes("positive_counts_below_the_threshold_are_hidden_a.1dc97093"), "the suppression rule is bilingual"); const touchedSources = [page, reportPage, reviewPage, operatorPage, deliveryMode].join("\n"); const touchedKeys = new Set(touchedSources.match(/i18n:govoplan-campaign\.[a-z0-9_]+\.[a-f0-9]{8}/g) ?? []); for (const key of touchedKeys) { const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const catalogEntries = [...translationCatalog.matchAll(new RegExp(`"${escapedKey}":\\s*("(?:[^"\\\\]|\\\\.)*")`, "g"))]; assert.equal(catalogEntries.length, 2, `${key} is present exactly once in both language catalogs`); const english = JSON.parse(catalogEntries[0][1]); const german = JSON.parse(catalogEntries[1][1]); assert.notEqual(english.trim(), "", `${key} has a non-empty English translation`); assert.notEqual(german.trim(), "", `${key} has a non-empty German translation`); } const sliceSections = [...translationCatalog.matchAll(/ "i18n:govoplan-campaign\.campaign_reports_available_to_you\.f14fa403":[\s\S]*? "i18n:govoplan-campaign\.worker_queue_committed_value0_message_s_and_publ\.24400d3c":.*\n/g)]; assert.equal(sliceSections.length, 2, "the current slice has one contiguous English and German catalog section"); const newEnglishEntries = [...sliceSections[0][0].matchAll(/"(i18n:govoplan-campaign\.[a-z0-9_]+\.[a-f0-9]{8})":\s*("(?:[^"\\]|\\.)*")/g)]; for (const [, key, encodedEnglish] of newEnglishEntries) { const english = JSON.parse(encodedEnglish); const digest = createHash("sha1").update(english).digest("hex").slice(0, 8); const slug = english.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+/, "").slice(0, 48); assert.equal(key, `i18n:govoplan-campaign.${slug}.${digest}`, `${key} uses the normalized source slug and exact SHA-1 suffix`); assert(touchedKeys.has(key), `${key} is referenced by the current Campaign UI slices`); } console.log("aggregate report UI structure checks passed");