From 923b8328914ce9d2c53cfef9068f1add9706d90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 10 Sep 2026 03:49:32 +0200 Subject: [PATCH] test(e2e): correct three claims the report journey's comments make MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mobile exclusion carried an inherited second reason — that mobile emulation emits no download event for the panel's anchor click. The precedent it came from contradicts itself: the JSON example-download test in `settings-export.spec.ts` asserts a real download event in the mobile project, and that spec also measures this very panel's tap targets there. The honest statement is that the panel's mobile layout is covered elsewhere and this journey is about the artefact. The bytes are read off the download because the saved file is what the person ends up with, not because a consumed body reads back empty — Playwright buffers the response independently of the page. And the filename assertion covers the name the client anchor invents, not the route's `Content-Disposition`; the two differ by a word, so it is not contract coverage of the header. --- e2e/doctor-report.spec.ts | 12 ++++++------ playwright.config.ts | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/e2e/doctor-report.spec.ts b/e2e/doctor-report.spec.ts index ae5e34216..c11fdee63 100644 --- a/e2e/doctor-report.spec.ts +++ b/e2e/doctor-report.spec.ts @@ -290,12 +290,9 @@ async function generateReport(page: Page): Promise { const response = await responseArrived; const download = await downloadStarted; - // The bytes come off the DOWNLOAD, not off the response. The panel reads the - // response into a Blob, and a body a page has already consumed is not one - // Playwright can hand back — `response.body()` answers zero bytes here. The - // saved file is also the better subject: it is the artefact the person ends - // up with, so a build that produced a perfect response and saved something - // else would still be caught. + // The bytes come off the DOWNLOAD, not off the response, because the saved + // file is the artefact the person ends up with: a build that produced a + // perfect response and saved something else would still be caught. const saved = await download.path(); expect(saved, "the panel saved the generated report").toBeTruthy(); const bytes = await readFile(saved!); @@ -351,6 +348,9 @@ function expectRealPdf(report: GeneratedReport): void { // The route declares the length it sent; a disagreement means the body was // truncated on the way out, which a magic-number check alone would miss. expect(report.contentLength).toBe(String(report.bytes.byteLength)); + // The name the CLIENT anchor invents, not the route's `Content-Disposition` + // — the two differ by a word today. This says the panel saved a PDF, and it + // is not contract coverage of the header. expect(report.filename).toMatch(/\.pdf$/); } diff --git a/playwright.config.ts b/playwright.config.ts index 43064c4a2..ae8df2f73 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -152,13 +152,13 @@ export default defineConfig({ // through stable data-slots, not a mobile layout, so it runs in one // project. "vaccinations.spec.ts", - // The doctor-report journey seeds a few weeks of readings into the one - // shared account, presses Generate and reads the PDF back off the - // download. Two projects doing that in parallel would leave a second - // set of rows in the window one of them is asserting an empty report - // for — and mobile emulation emits no `download` event for the - // anchor click the panel makes, so the artefact would be unreachable - // there anyway. + // The doctor-report journey seeds a few weeks of readings into its own + // account, presses Generate and reads the PDF back off the download. + // Two projects doing that in parallel would leave a second set of rows + // in the window one of them is asserting an empty report for, and would + // spend the shared hourly export bucket twice over. The panel's mobile + // layout is covered by `settings-export.spec.ts`, which measures its + // tap targets there; this journey is about the artefact. "doctor-report.spec.ts", // Its delegate half MOVES the session's record selector, so it runs in // exactly one project for the reason written above the fence specs.