/** * The phone's primary navigation (plan 016 B2). * * Three of these are about the thing that makes a second nav dangerous: * it has to agree with the first one. `bottom-nav` emits the same * bubbling, composed `navigate` event `app-sidebar` does and listens * for that event globally, so a navigation from anywhere — a card, a * detail view, the drawer's own sidebar — moves its highlight too. A * tab bar that only tracks its own clicks looks right until the moment * the user arrives somewhere by another route. */ import { describe, expect, it, beforeEach } from 'vitest'; import '@components/bottom-nav/bottom-nav'; import type { BottomNav } from '@components/bottom-nav/bottom-nav'; import { fixture, shadow, shadowAll, update } from '@test/support/render'; import { resetHarness } from '@test/support/harness'; type Nav = BottomNav; const tabs = (el: HTMLElement) => shadowAll(el, 'nav button'); /** Resolve on one occurrence of an event, or reject loudly on time. */ const once = (el: Element, name: string, timeoutMs = 2000) => new Promise((resolve, reject) => { const timer = setTimeout( () => reject(new Error(`${name} never fired`)), timeoutMs, ); el.addEventListener(name, () => { clearTimeout(timer); resolve(); }, { once: true }); }); describe('bottom-nav', () => { beforeEach(() => { resetHarness(); }); it('offers the four phone destinations and a way to the rest', async () => { const el = await fixture