From f38954f2ae1423c91ff8043ef67cb8083b5aee57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 22 Oct 2026 17:02:27 +0200 Subject: [PATCH] test(e2e): read the reduced-motion sheet before its first frame The check sampled getAnimations() once after the sheet showed, which passes or fails on whether WebKit drew a frame in between. It now reads the sheet and backdrop the moment they are inserted, the worst case, and is deterministic: it fails every time against the old classes. The other measurements in the spec already wait on polls, rendered frames or layout. --- e2e/bottom-sheet.spec.ts | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/e2e/bottom-sheet.spec.ts b/e2e/bottom-sheet.spec.ts index 78ba171a9..51cee6264 100644 --- a/e2e/bottom-sheet.spec.ts +++ b/e2e/bottom-sheet.spec.ts @@ -524,13 +524,37 @@ test.describe("the bottom sheet", () => { test("under reduced motion it opens without a slide", async ({ page }) => { await page.emulateMedia({ reducedMotion: "reduce" }); await page.goto("/mood"); + await expect(page.locator('[data-testid="bottom-nav-more"]')).toBeVisible(); + // Read the sheet the moment it is inserted, before the browser has drawn + // a frame of it: that is when a slide that exists at all is still + // running, however short it was made. A read after it shows depends on + // frames having been drawn in between, which WebKit in the CI container + // does not promise, so a later read alone can pass or fail at random. + await page.evaluate(() => { + const w = window as unknown as { __sheetAtInsert?: unknown }; + const watch = new MutationObserver(() => { + const sheet = document.querySelector( + '[data-testid="bottom-nav-more-sheet"]', + ); + const overlay = document.querySelector('[data-slot="sheet-overlay"]'); + if (!sheet || !overlay || w.__sheetAtInsert) return; + watch.disconnect(); + w.__sheetAtInsert = [sheet, overlay].map((el) => ({ + name: getComputedStyle(el).animationName, + animations: el.getAnimations().length, + })); + }); + watch.observe(document.body, { childList: true, subtree: true }); + }); await page.locator('[data-testid="bottom-nav-more"]').tap(); await expect(more(page)).toBeVisible(); - expect( - await more(page).evaluate( - (el) => - el.getAnimations().filter((a) => a.playState === "running").length, - ), - ).toBe(0); + const atInsert = await page.evaluate( + () => + (window as unknown as { __sheetAtInsert?: unknown }).__sheetAtInsert, + ); + expect(atInsert).toEqual([ + { name: "none", animations: 0 }, + { name: "none", animations: 0 }, + ]); }); });