diff --git a/tests/browser/journey-integration.spec.ts b/tests/browser/journey-integration.spec.ts index 57be334..a74753e 100644 --- a/tests/browser/journey-integration.spec.ts +++ b/tests/browser/journey-integration.spec.ts @@ -18,6 +18,16 @@ const sections = [ test.beforeEach(async ({ page }) => installSceneInstrumentation(page)); + +/** + * The gantry window pre-draws its hover twin for the exit it rests on, which + * is Start at load. That is a window texture, not a roadside sign, so it is + * left out of the roadside label checks; Start never has a roadside sign. + */ +function roadsideLabels(labels: readonly string[]): string[] { + return labels.filter((label) => label !== 'Start'); +} + test('keeps navigation, HUD, progress, chapter, and arrival on the same next-frame section snapshot', async ({ page, distUrl, @@ -105,7 +115,7 @@ test('draws only the independently eligible next roadside sign during passive fo await waitForOneAnimationFrame(page); await expect.poll(async () => (await readSceneInstrumentation(page)).routeLabelsDrawn).toContain(oracle.expectedLabel); - const labels = (await readSceneInstrumentation(page)).routeLabelsDrawn; + const labels = roadsideLabels((await readSceneInstrumentation(page)).routeLabelsDrawn); expect([...new Set(labels)]).toEqual([oracle.expectedLabel]); }); @@ -235,12 +245,12 @@ test('shows exactly one destination sign for a navigator click and suppresses hi await expect(page.locator('#selected-builds-heading')).toBeFocused(); await page.waitForTimeout(2_400); const afterRepeat = await readSceneInstrumentation(page); - expect(afterRepeat.routeLabelsDrawn).toEqual(['Selected builds']); + expect(roadsideLabels(afterRepeat.routeLabelsDrawn)).toEqual(['Selected builds']); expect(countSignPresentations(afterRepeat.signFrames, 'selected-builds')).toBe(1); await page.goBack({ waitUntil: 'domcontentloaded' }); await page.waitForTimeout(400); - expect((await readSceneInstrumentation(page)).routeLabelsDrawn).toEqual(['Selected builds']); + expect(roadsideLabels((await readSceneInstrumentation(page)).routeLabelsDrawn)).toEqual(['Selected builds']); }); test('keeps the non-navigator Explore work section jump sign-suppressed', async ({ @@ -430,7 +440,7 @@ test('moves an already-readable portrait sign into navigator-safe placement with const instrumentation = await readSceneInstrumentation(page); expect(countSignPresentations(instrumentation.signFrames, 'profile')).toBe(1); - expect(instrumentation.routeLabelsDrawn).toEqual(['Profile']); + expect(roadsideLabels(instrumentation.routeLabelsDrawn)).toEqual(['Profile']); }); test('re-arms passive signage after a navigator round trip to Start', async ({ @@ -495,7 +505,7 @@ test('reconciles an idle rapid jump to the latest active route without flashing frame.targetId === 'selected-builds' ))?.phase, { intervals: [16], timeout: 5_000 }).toBe('dwell'); const instrumentation = await readSceneInstrumentation(page); - expect([...new Set(instrumentation.routeLabelsDrawn)]) + expect([...new Set(roadsideLabels(instrumentation.routeLabelsDrawn))]) .toEqual(['Selected builds']); const dwell = instrumentation.signFrames.findLast((frame) => ( frame.targetId === 'selected-builds' && frame.phase === 'dwell' diff --git a/tests/browser/title-navigation.spec.ts b/tests/browser/title-navigation.spec.ts index 27d5a1a..317901b 100644 --- a/tests/browser/title-navigation.spec.ts +++ b/tests/browser/title-navigation.spec.ts @@ -8,8 +8,11 @@ test('desktop navigation docks without stretching labels or shifting the documen await page.evaluate(() => document.fonts.ready); const nav = page.locator('.site-navigation'); await expect(nav).toHaveAttribute('data-enhanced', 'true'); + // Since round 5 the bar is a full-bleed overhead gantry: it is docked at + // the top and unscaled from the first frame instead of growing into place. const surfaceScale = () => nav.evaluate(el => new DOMMatrixReadOnly(getComputedStyle(el, '::before').transform).a); - expect(await surfaceScale()).toBeLessThan(1); + expect(await surfaceScale()).toBe(1); + expect((await nav.boundingBox())!.y).toBeLessThan(1); const label = nav.locator('a').first(); const initialFont = await label.evaluate(el => getComputedStyle(el).fontSize); // Measure the content beside this fixed header, not unrelated lazy media @@ -26,7 +29,7 @@ test('desktop navigation docks without stretching labels or shifting the documen expect(await label.evaluate(el => getComputedStyle(el).fontSize)).toBe(initialFont); expect(await heroGeometry()).toEqual(initialHero); await page.evaluate(() => scrollTo(0, 0)); - await expect.poll(async () => (await nav.boundingBox())!.y).toBeGreaterThan(10); + await expect.poll(async () => (await nav.boundingBox())!.y).toBeLessThan(1); }); test('selected navigation has rounded inset highlights', async ({ page, distUrl }) => { @@ -34,7 +37,16 @@ test('selected navigation has rounded inset highlights', async ({ page, distUrl const disclosure = page.locator('.site-navigation summary'); if (await disclosure.isVisible()) await disclosure.click(); const selected = page.locator('.site-navigation a[aria-current="page"]'); - expect(await selected.evaluate(el => parseFloat(getComputedStyle(el).borderTopLeftRadius))).toBeGreaterThanOrEqual(5); + // On the desktop gantry the current exit is marked by its amber lane lamp + // (the li::after rule) rather than a rounded inset; the menu keeps the inset. + const marker = await selected.evaluate(el => { + const lamp = getComputedStyle(el.parentElement!, '::after'); + return { + radius: parseFloat(getComputedStyle(el).borderTopLeftRadius), + lamp: lamp.content !== 'none' && parseFloat(lamp.blockSize) >= 2, + }; + }); + expect(marker.radius >= 5 || marker.lamp).toBe(true); await selected.focus(); await page.keyboard.press('Shift'); expect(await selected.evaluate(el => getComputedStyle(el).outlineStyle)).not.toBe('none');