From 1232d5dfb27acfb2d3f8499af33c2b2d0c4a9fa9 Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Sun, 6 Sep 2026 06:05:04 +0200 Subject: [PATCH] test(pdf): enforce date layout baselines --- .../src/templates/shared/date-layout.test.tsx | 68 +++++++++++++----- .../pdf/test-artifacts/date-layout/README.md | 8 ++- .../test-artifacts/date-layout/REMEDIATION.md | 14 ++++ .../date-layout/chikorita-ltr.json | 4 ++ .../date-layout/chikorita-ltr.pdf | Bin 6391 -> 0 bytes .../date-layout/chikorita-rtl.json | 4 ++ .../date-layout/chikorita-rtl.pdf | Bin 8834 -> 0 bytes .../test-artifacts/date-layout/ditto-ltr.json | 4 ++ .../test-artifacts/date-layout/ditto-ltr.pdf | Bin 6096 -> 0 bytes .../test-artifacts/date-layout/ditto-rtl.json | 4 ++ .../test-artifacts/date-layout/ditto-rtl.pdf | Bin 8598 -> 0 bytes 11 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 packages/pdf/test-artifacts/date-layout/REMEDIATION.md delete mode 100644 packages/pdf/test-artifacts/date-layout/chikorita-ltr.pdf delete mode 100644 packages/pdf/test-artifacts/date-layout/chikorita-rtl.pdf delete mode 100644 packages/pdf/test-artifacts/date-layout/ditto-ltr.pdf delete mode 100644 packages/pdf/test-artifacts/date-layout/ditto-rtl.pdf diff --git a/packages/pdf/src/templates/shared/date-layout.test.tsx b/packages/pdf/src/templates/shared/date-layout.test.tsx index 20d0004ce..3fa20b217 100644 --- a/packages/pdf/src/templates/shared/date-layout.test.tsx +++ b/packages/pdf/src/templates/shared/date-layout.test.tsx @@ -4,8 +4,9 @@ import type { Template } from "@reactive-resume/schema/templates"; import type { TextItem } from "pdfjs-dist/types/src/display/api"; import type { RasterizedPdfPage } from "../../semantic/test/rasterize-pdf"; import { createHash } from "node:crypto"; -import { mkdirSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; import { pdf, renderToBuffer } from "@react-pdf/renderer"; import { encode } from "fast-png"; @@ -57,6 +58,26 @@ const dateMarkers = [ type DateMarker = (typeof dateMarkers)[number]; +const expectedMissingMarkers = { + azurill: [], + bronzor: [], + chikorita: [], + ditgar: [], + ditto: [], + gengar: [], + glalie: [], + kakuna: [], + lapras: [], + leafish: [], + meowth: ["EXP_NO_PERIOD"], + onyx: [], + pikachu: [], + rhyhorn: [], + scizor: [], +} as const satisfies Record; + +const baselineDirectory = join(dirname(fileURLToPath(import.meta.url)), "../../../test-artifacts/date-layout"); + type PdfPageText = { pageNumber: number; items: TextItem[]; @@ -418,6 +439,17 @@ const coordinatesFor = (result: RenderedFixture, markers: readonly DateMarker[]) ]), ); +const sha256 = (bytes: Uint8Array) => createHash("sha256").update(bytes).digest("hex"); + +const fixtureEvidence = (result: RenderedFixture, coordinates: Record) => { + const rasterPngs = result.raster.map((page) => encode(page)); + return { + pages: result.pages.map((page) => ({ pageNumber: page.pageNumber, itemCount: page.items.length })), + rasterSha256: rasterPngs.map(sha256), + coordinates, + }; +}; + const requiredMarkers = (result: RenderedFixture) => { const text = textFor(result); for (const marker of dateMarkers) expect(text).toContain(marker); @@ -428,23 +460,22 @@ const writeArtifacts = (name: string, result: RenderedFixture, coordinates: Reco const output = process.env.DATE_LAYOUT_ARTIFACT_DIR; if (!output) return; mkdirSync(output, { recursive: true }); - writeFileSync(join(output, `${name}.pdf`), result.bytes); - writeFileSync( - join(output, `${name}.json`), - JSON.stringify( - { - pages: result.pages.map((page) => ({ pageNumber: page.pageNumber, itemCount: page.items.length })), - coordinates, - }, - null, - 2, - ), - ); + writeFileSync(join(output, `${name}.json`), `${JSON.stringify(fixtureEvidence(result, coordinates), null, "\t")}\n`); for (const [index, page] of result.raster.entries()) { writeFileSync(join(output, `${name}-page-${index + 1}.png`), encode(page)); } }; +const assertFixtureBaseline = (name: string, result: RenderedFixture, coordinates: Record): void => { + if (process.env.DATE_LAYOUT_ARTIFACT_DIR) return; + const evidence = fixtureEvidence(result, coordinates); + expect(JSON.parse(readFileSync(join(baselineDirectory, `${name}.json`), "utf8"))).toEqual(evidence); + for (const index of result.raster.keys()) { + const expectedPng = readFileSync(join(baselineDirectory, `${name}-page-${index + 1}.png`)); + expect(sha256(expectedPng)).toBe(evidence.rasterSha256[index]); + } +}; + type HostNode = { type: string; style?: unknown; @@ -508,6 +539,7 @@ describe("date layout characterization (#3155, #2841)", () => { } for (const marker of dateMarkers) expect(markerItems(result, marker), marker).toHaveLength(1); writeArtifacts(`${template}-${direction}`, result, coordinates); + assertFixtureBaseline(`${template}-${direction}`, result, coordinates); }); it("records default date evidence for every template without claiming parity geometry", async () => { @@ -515,10 +547,12 @@ describe("date layout characterization (#3155, #2841)", () => { for (const template of templates) { const result = await renderFixture(dateFixture(), template); const coordinates = coordinatesFor(result, dateMarkers); + const missingMarkers = dateMarkers.filter((marker) => markerItems(result, marker).length === 0); + expect(missingMarkers, template).toEqual(expectedMissingMarkers[template]); evidence[template] = { pageCount: result.pages.length, textItemCount: allItems(result).length, - missingMarkers: dateMarkers.filter((marker) => markerItems(result, marker).length === 0), + missingMarkers, rasterSha256: result.raster.map((page) => createHash("sha256").update(page.data).digest("hex")), coordinates, }; @@ -526,7 +560,9 @@ describe("date layout characterization (#3155, #2841)", () => { const output = process.env.DATE_LAYOUT_ARTIFACT_DIR; if (output) { mkdirSync(output, { recursive: true }); - writeFileSync(join(output, "all-templates.json"), JSON.stringify(evidence, null, 2)); + writeFileSync(join(output, "all-templates.json"), `${JSON.stringify(evidence, null, "\t")}\n`); + } else { + expect(JSON.parse(readFileSync(join(baselineDirectory, "all-templates.json"), "utf8"))).toEqual(evidence); } }); diff --git a/packages/pdf/test-artifacts/date-layout/README.md b/packages/pdf/test-artifacts/date-layout/README.md index a3fee1d48..34673859b 100644 --- a/packages/pdf/test-artifacts/date-layout/README.md +++ b/packages/pdf/test-artifacts/date-layout/README.md @@ -1,9 +1,15 @@ # Plan 24 Step 1 — date layout characterization -Revision under test: `66c25efe1` (`origin/main`), branch `codex/issue-3155-date-layout-characterization`. +Generation revision: `58ee4eead7843105da20f8a177e7d250b24c3a87` (pre-remediation characterization merge). +Comparison ref: `368858a56fc9c3152b540c39829908e2c3ea04c5` (`origin/main` at review). +Branch: `codex/issue-3155-date-layout-characterization`. + +JSON and PNG files are executable baselines. Raw PDFs are intentionally omitted because renderer metadata is nondeterministic. The durable fixture is [`date-layout.test.tsx`](../../src/templates/shared/date-layout.test.tsx). It renders the same unchanged resume data through Chikorita and Ditto in LTR and RTL modes, extracts PDF text coordinates, rasterizes each PDF page, and records default evidence for all 15 templates. +Remediation details: [`REMEDIATION.md`](REMEDIATION.md). + ## Matrix coverage - Standard date-bearing sections: Awards (`date`), Certifications (`date`), Education (`period`), Experience (`period` and two nested role periods), Projects (`period`), Publications (`date`), and Volunteer (`period`). diff --git a/packages/pdf/test-artifacts/date-layout/REMEDIATION.md b/packages/pdf/test-artifacts/date-layout/REMEDIATION.md new file mode 100644 index 000000000..63b4997a9 --- /dev/null +++ b/packages/pdf/test-artifacts/date-layout/REMEDIATION.md @@ -0,0 +1,14 @@ +# Date-layout baseline remediation + +- Normal focused runs compare Chikorita/Ditto LTR+RTL JSON coordinates, page counts, and PNG hashes against checked-in artifacts. +- All-template evidence asserts exact `missingMarkers`: `[]` for 14 templates and `['EXP_NO_PERIOD']` for Meowth, the documented blank-period exception. +- Raw PDFs are omitted; renderer `CreationDate` metadata made PDF bytes nondeterministic. +- Provenance is fixed to generation revision `58ee4eead7843105da20f8a177e7d250b24c3a87` and comparison ref `368858a56fc9c3152b540c39829908e2c3ea04c5`. + +Verification: + +- Focused Vitest: `pnpm exec vitest run src/templates/shared/date-layout.test.tsx` — 1 file, 7 tests, twice with baseline comparison. +- PDF typecheck: `pnpm --filter @reactive-resume/pdf run typecheck` — pass. +- Targeted Biome: `pnpm exec biome check packages/pdf/src/templates/shared/date-layout.test.tsx` — pass. +- Boundaries: `pnpm exec turbo boundaries` — pass. +- Diff checks: `git diff --check` — pass. diff --git a/packages/pdf/test-artifacts/date-layout/chikorita-ltr.json b/packages/pdf/test-artifacts/date-layout/chikorita-ltr.json index 3f8bfd23a..d236bc37c 100644 --- a/packages/pdf/test-artifacts/date-layout/chikorita-ltr.json +++ b/packages/pdf/test-artifacts/date-layout/chikorita-ltr.json @@ -9,6 +9,10 @@ "itemCount": 38 } ], + "rasterSha256": [ + "5b673865c8e5c8d847f5afad2d80d541639b5db8276e25b18ee4572a79564066", + "2e72c805845fea245b51427b104e901538af8e5c594b51810e5ee23df5bb23a3" + ], "coordinates": { "EXP_LONG": [ { diff --git a/packages/pdf/test-artifacts/date-layout/chikorita-ltr.pdf b/packages/pdf/test-artifacts/date-layout/chikorita-ltr.pdf deleted file mode 100644 index e25a481075767d43e6f4cae1f86142bcb19801f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6391 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 diff --git a/packages/pdf/test-artifacts/date-layout/chikorita-rtl.json b/packages/pdf/test-artifacts/date-layout/chikorita-rtl.json index bd45b1670..1a762b846 100644 --- a/packages/pdf/test-artifacts/date-layout/chikorita-rtl.json +++ b/packages/pdf/test-artifacts/date-layout/chikorita-rtl.json @@ -9,6 +9,10 @@ "itemCount": 41 } ], + "rasterSha256": [ + "e192c24c35e5442b4ae0aa278b84f7991b54c4be5fb82ca13642dc6f2c6bde32", + "631686b14720c12e67f426ab56c65343a83997836bc7d9db371b81f8b02f7d2e" + ], "coordinates": { "EXP_LONG": [ { diff --git a/packages/pdf/test-artifacts/date-layout/chikorita-rtl.pdf b/packages/pdf/test-artifacts/date-layout/chikorita-rtl.pdf deleted file mode 100644 index cba468750eba43896b7e2e866606b8c2ecce42c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8834 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 HY5@BeKA?mE diff --git a/packages/pdf/test-artifacts/date-layout/ditto-rtl.json b/packages/pdf/test-artifacts/date-layout/ditto-rtl.json index 584ec8707..184232e2d 100644 --- a/packages/pdf/test-artifacts/date-layout/ditto-rtl.json +++ b/packages/pdf/test-artifacts/date-layout/ditto-rtl.json @@ -9,6 +9,10 @@ "itemCount": 42 } ], + "rasterSha256": [ + "25e05e71a84e043e3e925f2580044d7493ec6f51fc3e22454edcbe562767f5a6", + "ea56e1dc8f6e96999270a7bc20864cbffb3723b07d3e72557e4828440b7f044d" + ], "coordinates": { "EXP_LONG": [ { diff --git a/packages/pdf/test-artifacts/date-layout/ditto-rtl.pdf b/packages/pdf/test-artifacts/date-layout/ditto-rtl.pdf deleted file mode 100644 index d830823aaa037f8f3e828b6f30a45da117329a3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8598 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