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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user