From 199013197eb67e5e264dfe0ecf3e18da687dc652 Mon Sep 17 00:00:00 2001 From: Anso Date: Wed, 23 Sep 2026 21:56:33 -0400 Subject: [PATCH] fix(e2e): read the launcher morph after the transition settles (#1971) The hamburger bars move through a 150ms CSS transition (clamped only under Reduced motion). The test read the closed computed style immediately after an Escape, which could land inside the close transition and capture the open values; reopening then produced an identical read and the morph assertion failed intermittently depending on the suite account's motion preference. Capture the closed style while the bar is at rest before any toggle, and poll the open style instead of sampling once. The assertion still proves the bar moves between the closed and open states. --- e2e/desktop-navigation.spec.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/e2e/desktop-navigation.spec.ts b/e2e/desktop-navigation.spec.ts index 882f43369..35242d0e2 100644 --- a/e2e/desktop-navigation.spec.ts +++ b/e2e/desktop-navigation.spec.ts @@ -197,10 +197,6 @@ test.describe('Desktop navigation styles', () => { test('the launcher hamburger morphs open/closed and does not animate under Reduced motion', async ({ page }) => { const trigger = page.getByRole('button', { name: 'Open navigation launcher' }); await expect(trigger).toHaveAttribute('data-state', 'closed'); - await trigger.click(); - await expect(trigger).toHaveAttribute('data-state', 'open'); - await page.keyboard.press('Escape'); - await expect(trigger).toHaveAttribute('data-state', 'closed'); // The bar actually moves open vs. closed, not just a duration-clamp check. // Read translate and rotate alongside transform: Tailwind v4 compiles these @@ -212,9 +208,21 @@ test.describe('Desktop navigation styles', () => { const s = getComputedStyle(el); return `${s.translate}|${s.rotate}|${s.transform}`; }; + // Read the closed bar while it is at rest, before anything has animated. const closedMorph = await bar.evaluate(morphState); + await trigger.click(); await expect(trigger).toHaveAttribute('data-state', 'open'); + await page.keyboard.press('Escape'); + await expect(trigger).toHaveAttribute('data-state', 'closed'); + + await trigger.click(); + await expect(trigger).toHaveAttribute('data-state', 'open'); + // The bars move through a CSS transition (150ms, clamped under Reduced + // motion), so a computed-style read right after the data-state flip can + // land before the transition settles and report the closed values. Poll + // until the morph differs instead of sampling once. + await expect.poll(() => bar.evaluate(morphState), { timeout: 5_000 }).not.toBe(closedMorph); const openMorph = await bar.evaluate(morphState); expect(openMorph).not.toBe(closedMorph); await page.keyboard.press('Escape');