--- phase: 07-mobile-test-harness plan: "03" subsystem: test-harness tags: [playwright, e2e, layout, tap-targets, overflow, accessibility, self-validation] dependency_graph: requires: - "apps/pwa/playwright.config.ts (07-01) — iphone/pixel project matrix, serviceWorkers: 'block'" - "apps/pwa/e2e/global-setup.ts (07-02) — /health readiness gate + DB seed (calendar_id=10, E2E Grocery List)" provides: - "apps/pwa/e2e/layout.spec.ts — UI-SPEC Rules 1-4 assertions (tap targets, overflow, in-viewport, accessible names)" - "Harness self-validation: addStyleTag injected-defect proofs for Rule 1 + Rule 2" - "30 tests (15 per profile) — all passing on iphone (WebKit) and pixel (Chromium)" affects: - "Phase 07 plan 04 (calendar.spec.ts / lists.spec.ts share the same harness foundation)" - "Phase 08 CI (layout.spec.ts is a PR regression step)" tech_stack: added: [] patterns: - "boundingBox() — rendered geometry measurement, not CSS-declared values" - "page.evaluate(() => scrollWidth/clientWidth) — DOM overflow measurement" - "page.addStyleTag + handle.evaluate(el => el.remove()) — injected-defect proof pattern" - "getByRole('navigation', { name }) scoping — avoids strict-mode collision between BottomTabBar and DesktopNav" - "getByText('FamilySync', { exact: true }) — avoids matching 'Install FamilySync' install-prompt" key_files: created: - apps/pwa/e2e/layout.spec.ts modified: - apps/pwa/e2e/global-setup.ts decisions: - "D-03-SCOPE-NAV: On mobile profiles (390px/412px), AppNav renders PhoneNav as
(not a nav landmark) — only BottomTabBar exposes