diff --git a/tests/ui-my-day-calendar.spec.ts b/tests/ui-my-day-calendar.spec.ts index bc48b31903..5a84eee63e 100644 --- a/tests/ui-my-day-calendar.spec.ts +++ b/tests/ui-my-day-calendar.spec.ts @@ -65,6 +65,20 @@ async function expectMonth(calendar: Locator, title: string) { await expect(calendar.getByRole("heading", { level: 2, name: title })).toBeVisible(); } +/** + * Clicks a calendar control and waits for what it does, clicking again if the first click left no + * trace. Firefox on main dropped one of these clicks in three runs in a row on 13 Oct 2026 (once the + * chosen day, once Today), each time after the calendar had settled. The outcome is still asserted + * in full; a repeat click is harmless because both actions are idempotent. + */ +async function clickUntil(control: Locator, outcome: () => Promise) { + await expect(async () => { + // Today disappears once October shows, so a click that landed but rendered slowly is not repeated. + if (await control.isVisible()) await control.click({ timeout: 5_000 }); + await outcome(); + }).toPass({ timeout: 20_000, intervals: [1_000, 2_000, 4_000] }); +} + async function expectNoSidewaysScroll(page: Page, label: string) { const { scrollWidth, clientWidth } = await page.evaluate(() => ({ scrollWidth: document.documentElement.scrollWidth, @@ -102,13 +116,14 @@ test("moves between months, shows your older shifts, and returns to today", asyn await expect(page.getByTestId("my-day-calendar-history-notice")).toHaveCount(0); expect(datedReads.some((query) => query.includes("from=2026-07-31"))).toBe(true); - await calendar.getByTestId("my-day-calendar-day-2026-08-12").click(); - await expect(calendar.getByTestId("my-day-calendar-day-2026-08-12")).toHaveAttribute("aria-pressed", "true"); + const chosenDay = calendar.getByTestId("my-day-calendar-day-2026-08-12"); + await clickUntil(chosenDay, () => expect(chosenDay).toHaveAttribute("aria-pressed", "true", { timeout: 5_000 })); const day = calendar.getByTestId("my-day-calendar-day"); await expect(day.getByTestId(`my-day-calendar-item-shift:${older.id}`)).toBeVisible(); - await calendar.getByTestId("my-day-calendar-today").click(); - await expectMonth(calendar, "October 2026"); + await clickUntil(calendar.getByTestId("my-day-calendar-today"), () => + expect(calendar.getByRole("heading", { level: 2, name: "October 2026" })).toBeVisible({ timeout: 5_000 }), + ); await expect(calendar.getByTestId("my-day-calendar-today")).toHaveCount(0); await expect(today).toHaveAttribute("aria-pressed", "true"); }); diff --git a/tests/ui-route-coverage.spec.ts b/tests/ui-route-coverage.spec.ts index b9f41f1a61..2fe50d6d1c 100644 --- a/tests/ui-route-coverage.spec.ts +++ b/tests/ui-route-coverage.spec.ts @@ -500,8 +500,13 @@ test.describe("previously uncovered production routes", () => { // the URL: a same-route `?ids=` soft navigation fires no document load, which // `waitForURL` waits for, and inside `Promise.all` its timeout also hid whether the // click itself ever landed (WebKit, 12 Oct 2026). - await remove.click(); - await expect(currentPage).toHaveURL(/\/dsm\/compare\?ids=bipolar-ii-disorder$/, { timeout: 30_000 }); + // iPad WebKit on main dropped this click once on 13 Oct 2026 (URL unchanged for 30 s), so a + // click that leaves no trace is repeated while the button is still there. Removal must still + // land on exactly the remaining id. + await expect(async () => { + if (await remove.isVisible()) await remove.click({ timeout: 5_000 }); + await expect(currentPage).toHaveURL(/\/dsm\/compare\?ids=bipolar-ii-disorder$/, { timeout: 10_000 }); + }).toPass({ timeout: 40_000, intervals: [1_000, 2_000, 4_000] }); // Empty dashed panel is suppressed in favour of the compact slot rail // and inline starter chips when fewer than two diagnoses remain. await expect(currentPage.getByTestId("compare-slot-tile-compact").first()).toBeVisible();