style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
@@ -1,25 +1,25 @@
---
phase: 07-mobile-test-harness
plan: "03"
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)"
- '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)"
- '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)"
- '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"
- '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:
@@ -30,10 +30,10 @@ key_files:
decisions:
- "D-03-SCOPE-NAV: On mobile profiles (390px/412px), AppNav renders PhoneNav as <header> (not a nav landmark) — only BottomTabBar exposes <nav aria-label='Main navigation'>. No strict-mode collision in practice, but tap-target locators are scoped inside the nav landmark for robustness."
- "D-03-PHONENAV-TEXT: getByText('FamilySync', { exact: true }) required — the InstallPrompt renders 'Install FamilySync', which getByText('FamilySync') without exact:true matches as a substring, causing a strict-mode violation on WebKit."
- "D-03-SELF-VALIDATION: Self-validation proofs use addStyleTag + handle.evaluate(el => el.remove()) to inject and remove the defect style within the same test. No page.reload() needed — handle removal is synchronous and immediately clears the injected CSS."
- 'D-03-SELF-VALIDATION: Self-validation proofs use addStyleTag + handle.evaluate(el => el.remove()) to inject and remove the defect style within the same test. No page.reload() needed — handle removal is synchronous and immediately clears the injected CSS.'
metrics:
duration_seconds: 480
completed_date: "2026-06-11"
completed_date: '2026-06-11'
tasks_completed: 2
files_changed: 2
---
@@ -47,6 +47,7 @@ metrics:
`apps/pwa/e2e/layout.spec.ts` with four describe blocks covering:
**Rule 1/3/4 — BottomTabBar on /calendar (8 tests per profile)**
- Navigation landmark visible (Rule 4 — accessible name proof)
- Calendar tab boundingBox ≥ 44×44px (Rule 1)
- Lists tab boundingBox ≥ 44×44px (Rule 1)
@@ -56,16 +57,19 @@ metrics:
- New Event FAB boundingBox ≥ 56×56px (Rule 1 — larger threshold)
**Rule 1/3/4 — BottomTabBar on /lists (4 tests per profile)**
- Navigation landmark visible on /lists
- Calendar tab ≥ 44×44px on /lists
- Lists tab ≥ 44×44px on /lists
- BottomTabBar in-viewport on /lists
**Rule 2 — No horizontal overflow (2 tests per profile)**
- `scrollWidth ≤ clientWidth` on /calendar
- `scrollWidth ≤ clientWidth` on /lists
**Harness self-validation — injected defects (2 tests per profile)**
- Rule 1 proof: injects `nav[aria-label="Main navigation"] a { height: 20px !important }`, asserts height < 44, removes, asserts height ≥ 44 — proves boundingBox tracks rendered geometry
- Rule 2 proof: injects `body { width: 2000px !important }`, asserts scrollWidth > clientWidth, removes, asserts scrollWidth ≤ clientWidth — proves overflow detection is live
@@ -84,6 +88,7 @@ metrics:
### Auto-fixed Issues
**1. [Rule 1 - Bug] WebKit strict-mode violation: `getByText('FamilySync')` matched 2 elements**
- **Found during:** Task 1 first iphone run
- **Issue:** `getByText('FamilySync')` without `exact:true` also matched the `<div>Install FamilySync</div>` text in the InstallPrompt component, causing a strict-mode violation on WebKit (where the install prompt was visible).
- **Fix:** Changed to `getByText('FamilySync', { exact: true })` — matches only the `<span>FamilySync</span>` in PhoneNav.
@@ -91,6 +96,7 @@ metrics:
- **Commit:** 52e14a8
**2. [Rule 3 - Blocking] global-setup.ts: MariaDB TIMESTAMP rejected ISO 8601 format**
- **Found during:** Task 1 execution — global-setup failed before any spec could run
- **Issue:** `futureStart.toISOString().replace(/\.\d+Z$/, 'Z')` produces `'2026-06-12T05:58:35Z'` (with `T` separator), which MariaDB TIMESTAMP rejects with `Incorrect datetime value`. MariaDB requires `'YYYY-MM-DD HH:MM:SS'` format.
- **Fix:** Added `.replace('T', ' ')` and removed the trailing `Z` — produces `'2026-06-12 05:58:35'` which MariaDB TIMESTAMP accepts.
@@ -98,6 +104,7 @@ metrics:
- **Commit:** d3c6726 (fix(07-02))
**3. [Observation] DesktopNav nav landmark absent on mobile profiles — no strict-mode risk**
- **Found during:** Component analysis before writing locators
- **Issue:** The plan warned about strict-mode collision between BottomTabBar nav and DesktopNav nav, both named "Main navigation". In practice, on mobile profiles (390px/412px), `AppNav` renders `PhoneNav` (a `<header>`, not a nav), so DesktopNav's nav is absent. No collision occurs.
- **Fix:** Still scoped tap-target locators inside `getByRole('navigation', { name: 'Main navigation' })` for defensive robustness against any future layout change.