From b7d52dc3db90203261b5bbbd35437bfc9bfdb78f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 18:03:30 +0000 Subject: [PATCH 1/3] test(webkit): retry the patient panel tap and report the Dictionary label layout Main's Safari matrix after #3501 cleared both of that PR's checks and showed two new failures: - Installed-app QTc: after tapping the patient panel the fields never showed. The other five tests using the same helper passed in that shard, so the tap landed on a panel that was then replaced and remounted closed. Retry the tap until the fields show. - Dictionary at 768px on phone Safari: the Abbreviations label measured 72px of text in 56px. Local Chromium gives exactly 72px at the 320px layout and 80px at 768px, so Safari appears to keep the narrow layout after the resize. The check now prints the applied width, breakpoint and segment sizes when it fails, so the next run shows which. No test skipped or loosened; no app code changed. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01DCghuougzFFXRF3dQQEcYr --- tests/ui-dictionary.spec.ts | 26 +++++++++++++++++++++----- tests/ui-patient-number-field.spec.ts | 8 ++++++-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/tests/ui-dictionary.spec.ts b/tests/ui-dictionary.spec.ts index f42faa1f21..ba398f3a04 100644 --- a/tests/ui-dictionary.spec.ts +++ b/tests/ui-dictionary.spec.ts @@ -207,11 +207,27 @@ test("merges search and browse into one catalogue with a measured phone header", expect(Math.abs(scopeSegments[0] - scopeSegments[1])).toBeLessThanOrEqual(1); const abbreviationsRadio = toggle.getByRole("radio", { name: /Abbreviations/ }); const expectAbbreviationsLabelToFit = async () => { - const dimensions = await abbreviationsRadio.getByText("Abbreviations", { exact: true }).evaluate((label) => ({ - clientWidth: label.clientWidth, - scrollWidth: label.scrollWidth, - })); - expect(dimensions.scrollWidth).toBeLessThanOrEqual(dimensions.clientWidth); + const dimensions = await abbreviationsRadio.getByText("Abbreviations", { exact: true }).evaluate((label) => { + const segment = label.parentElement; + const style = segment ? getComputedStyle(segment) : null; + return { + clientWidth: label.clientWidth, + scrollWidth: label.scrollWidth, + // Read on failure only: which layout the browser applied at this width. + layout: { + innerWidth: window.innerWidth, + smMatches: window.matchMedia("(min-width: 40rem)").matches, + segmentWidth: Math.round(segment?.getBoundingClientRect().width ?? -1), + fontSize: style?.fontSize, + letterSpacing: style?.letterSpacing, + paddingLeft: style?.paddingLeft, + hintWidth: Math.round(label.nextElementSibling?.getBoundingClientRect().width ?? -1), + }, + }; + }); + expect(dimensions.scrollWidth, `Abbreviations label clipped: ${JSON.stringify(dimensions)}`).toBeLessThanOrEqual( + dimensions.clientWidth, + ); }; await expectAbbreviationsLabelToFit(); await expect(abbreviationsRadio).toBeChecked(); diff --git a/tests/ui-patient-number-field.spec.ts b/tests/ui-patient-number-field.spec.ts index b0432223b8..38e22631be 100644 --- a/tests/ui-patient-number-field.spec.ts +++ b/tests/ui-patient-number-field.spec.ts @@ -104,9 +104,13 @@ async function openPatientStrip(page: Page): Promise { // The panel's open state is React-controlled. A tap before hydration toggles // the native
without React's onToggle, so React's state and the // DOM can disagree and the field may never show. - await clickWhenHydrated(panel.locator("summary").first()); + // A streamed page can replace the panel after the tap, and the replacement mounts closed, so + // retry the tap until the fields show rather than trusting the first one. const crcl = page.getByTestId("patient-crcl"); - await expect(crcl).toBeVisible({ timeout: 15_000 }); + await expect(async () => { + if (!(await crcl.isVisible())) await clickWhenHydrated(panel.locator("summary").first()); + await expect(crcl).toBeVisible({ timeout: 5_000 }); + }).toPass({ timeout: 20_000 }); await waitForHydratedField(crcl); } From 899ae4f47aa699495c0c1b6afa7adc157cdcc34a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 18:09:00 +0000 Subject: [PATCH 2/3] test: re-tap the patient panel only while it is closed Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01DCghuougzFFXRF3dQQEcYr --- tests/ui-patient-number-field.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ui-patient-number-field.spec.ts b/tests/ui-patient-number-field.spec.ts index 38e22631be..60103fbf9a 100644 --- a/tests/ui-patient-number-field.spec.ts +++ b/tests/ui-patient-number-field.spec.ts @@ -105,10 +105,12 @@ async function openPatientStrip(page: Page): Promise { // the native
without React's onToggle, so React's state and the // DOM can disagree and the field may never show. // A streamed page can replace the panel after the tap, and the replacement mounts closed, so - // retry the tap until the fields show rather than trusting the first one. + // tap again whenever the panel is closed rather than trusting the first tap. Reading the + // panel's own open state never re-taps an open panel whose fields are still painting. const crcl = page.getByTestId("patient-crcl"); await expect(async () => { - if (!(await crcl.isVisible())) await clickWhenHydrated(panel.locator("summary").first()); + const open = await panel.evaluate((element) => (element as HTMLDetailsElement).open); + if (!open) await clickWhenHydrated(panel.locator("summary").first()); await expect(crcl).toBeVisible({ timeout: 5_000 }); }).toPass({ timeout: 20_000 }); await waitForHydratedField(crcl); From 9e0a529e378e5ac8ea9bfc4168dc6b0f5446790d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 18:10:16 +0000 Subject: [PATCH 3/3] test: hydrate and re-check the patient field inside the retry Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01DCghuougzFFXRF3dQQEcYr --- tests/ui-patient-number-field.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ui-patient-number-field.spec.ts b/tests/ui-patient-number-field.spec.ts index 60103fbf9a..4de9d72ddf 100644 --- a/tests/ui-patient-number-field.spec.ts +++ b/tests/ui-patient-number-field.spec.ts @@ -112,8 +112,10 @@ async function openPatientStrip(page: Page): Promise { const open = await panel.evaluate((element) => (element as HTMLDetailsElement).open); if (!open) await clickWhenHydrated(panel.locator("summary").first()); await expect(crcl).toBeVisible({ timeout: 5_000 }); - }).toPass({ timeout: 20_000 }); - await waitForHydratedField(crcl); + await waitForHydratedField(crcl); + // A replacement that lands after the field first painted mounts closed; this retries it. + await expect(crcl).toBeVisible({ timeout: 1_000 }); + }).toPass({ timeout: 30_000 }); } /**