import { expect, test } from "@playwright/test"; import fs from "node:fs/promises"; import path from "node:path"; import { previewDocumentHtml } from "../src/cvPreview"; const original = path.resolve("../docs/redesign/phase-5/p5-09-readiness/evidence/fidelity"); test("[PRES-C09 C12] original flowing/boundary fixtures retain native PDF page membership", async ({ page }) => { const baseline = JSON.parse(await fs.readFile(path.join(original, "fidelity-results.json"), "utf8")); for (const fixture of baseline.fixtures.filter((fixture: { pass: boolean }) => !fixture.pass)) { await page.setContent(previewDocumentHtml(await fs.readFile(path.join(original, fixture.fixture, "render.html"), "utf8"), 1122.52)); await expect.poll(() => page.evaluate(() => document.documentElement.dataset.cvPreviewReady)).toBe("true"); expect(await page.evaluate(() => Number(document.documentElement.dataset.cvPreviewPages)), fixture.fixture).toBe(fixture.pdfPages); const membership = await page.evaluate(() => { const width = Number(document.documentElement.dataset.cvPreviewWidth); const walker = document.createTreeWalker(document.querySelector(".page")!, NodeFilter.SHOW_TEXT); const markers: { token: string; page: number }[] = []; let node; while ((node = walker.nextNode())) for (const match of (node.textContent || "").matchAll(/\b[SEBPR]\d{2}\b/g)) { const range = document.createRange(); range.setStart(node, match.index!); range.setEnd(node, match.index! + match[0].length); markers.push({ token: match[0], page: Math.floor(range.getClientRects()[0].x / width) + 1 }); } return markers; }); expect(membership, fixture.fixture).toEqual(fixture.comparisons.map((marker: { token: string; pdfPage: number }) => ({ token: marker.token, page: marker.pdfPage }))); expect(await page.evaluate(() => document.body.innerText)).not.toContain("HIDDEN-MARKER"); } }); test("[PRES-C06 C09] pagination waits for image layout and publishes one settled measurement", async ({ page }) => { let releaseImage!: () => void; const gate = new Promise(resolve => { releaseImage = resolve; }); await page.route("**/pagination-photo.svg", async route => { await gate; await route.fulfill({ contentType: "image/svg+xml", body: '' }); }); const html = '
Synthetic fixture
'; await page.setContent(previewDocumentHtml(html, 1122.52), { waitUntil: "domcontentloaded" }); expect(await page.evaluate(() => document.documentElement.dataset.cvPreviewReady)).toBeUndefined(); await page.evaluate(() => { document.documentElement.dataset.readyEvents = "0"; window.addEventListener("cv-preview-ready", () => { document.documentElement.dataset.readyEvents = String(Number(document.documentElement.dataset.readyEvents) + 1); }); }); releaseImage(); await expect.poll(() => page.evaluate(() => document.documentElement.dataset.cvPreviewReady)).toBe("true"); expect(await page.evaluate(() => ({ events: document.documentElement.dataset.readyEvents, pages: document.documentElement.dataset.cvPreviewPages }))).toEqual({ events: "1", pages: "1" }); expect(await page.evaluate(() => document.querySelector("img")!.getBoundingClientRect().height)).toBeCloseTo(10 * 96 / 25.4, 1); await page.evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve())))); expect(await page.evaluate(() => document.documentElement.dataset.readyEvents)).toBe("1"); });