Files
familysync/.planning/milestones/v1.1-phases/14-desktop-e2e-coverage/14-CONTEXT.md
T
2026-06-18 22:21:38 -04:00

152 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 14: Desktop E2E Coverage - Context
**Gathered:** 2026-06-12
**Status:** Ready for planning
<domain>
## Phase Boundary
Add a `desktop` Playwright project (Desktop Chrome, wide viewport, no `hasTouch`) to
`apps/pwa/playwright.config.ts` and make the existing Phase 7 mobile-authored e2e specs
pass on a no-touch desktop viewport, so the Phase 8 CI regression gate validates the
**desktop** layout/flows in addition to the `iphone`/`pixel` mobile profiles.
The real work is the **spec-compat pass**, not CI plumbing — Phase 8 already runs
`pnpm test:e2e` and will pick up the new project automatically. No new test *capabilities*
are added; this is desktop-profile coverage of the layout/state bars Phase 7 already asserts.
**In scope:** desktop project config; per-spec review so the suite is green on desktop;
desktop-equivalent assertions where the mobile layout diverges.
**Out of scope:** new flows/features; live event-create against CalDAV (dev user 1 still has
no calendar credential — carried from Phase 7); Desktop WebKit; prod-SW / iOS-standalone testing.
</domain>
<decisions>
## Implementation Decisions
### Spec-Compat Strategy
- **D-01:** Keep **one set of spec files** (no separate `desktop.spec.ts`). Gate the genuinely
mobile-only tests with `test.skip()` keyed on project name (`desktop`), and add desktop-equivalent
assertions where the layout diverges. Cross-cutting tests (no-overflow, populated/empty/error
states) stay shared and run on all three profiles. Rationale: one source of truth, least
duplication, avoids drift between mobile and desktop copies of the same cross-cutting assertions.
- **D-02:** Prefer scoping/skip over deletion — do not weaken or remove the existing mobile
assertions to make desktop pass. The mobile profiles must remain exactly as authored in Phase 7.
### Desktop Gate Severity
- **D-03:** Desktop-profile failures are **blocking** — same severity as `iphone`/`pixel`.
A desktop regression must not be able to land on `main`. No `continue-on-error` / advisory
carve-out. (Resolves ROADMAP Phase 14 Success Criterion 3, which deferred blocking-vs-advisory
to planning.) Implication: the desktop specs must be deterministic before this merges —
if they flake, fix the spec, don't downgrade the gate.
### Desktop Assertion Depth
- **D-04:** **Parity-adapted** coverage. On desktop, positively assert the desktop equivalents:
DesktopNav sidebar (`nav[aria-label="Main navigation"]`) visible, nav tap targets, no horizontal
overflow, populated/empty/error states render (calendar grid, seeded event, lists card, empty
state, error heading + Retry). Skip only the assertions that have no desktop analog.
- **D-05:** Do **not** add "mobile chrome is absent on desktop" negative assertions (the rejected
"full divergence" option). Reason grounded in code: the `New Event` accessible name is **not**
mobile-only — `CalendarShell.tsx:424` renders a desktop-only toolbar "New Event" button sharing
the same name as the phone FAB. Asserting its absence would be wrong. Only the **56×56 FAB
geometry** check is mobile-specific.
### Desktop Profile / Viewport
- **D-06:** Single desktop project using `devices['Desktop Chrome']` (1280×720), **no Desktop WebKit**.
The Apple member is already covered on mobile Safari via the `iphone`/WebKit profile; Desktop
Chrome is sufficient for the shared/wall-browser use case. Keep the default viewport — no custom
width override unless planning finds the sidebar layout needs more horizontal room than 1280 gives.
### Claude's Discretion
- Exact mechanism for the skip gate (e.g. `test.skip(testInfo.project.name === 'desktop', ...)` vs.
`test.describe` blocks split by a `isDesktop` helper vs. project-level `grep`/`grepInvert`) — pick
the cleanest that keeps the shared cross-cutting tests un-duplicated. Planner/researcher to choose.
- Whether the desktop "New Event" toolbar button gets its own ≥44px tap-target assertion as the
desktop parity equivalent of the FAB's 56×56 check (recommended, but optional).
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### The harness being extended (Phase 7)
- `apps/pwa/playwright.config.ts` — the two-profile matrix to extend with a third `desktop` project;
documents the carried-forward auth/SW/baseURL/webServer decisions (D-01..D-10 in its header).
- `apps/pwa/e2e/layout.spec.ts` — the spec with the most mobile-only assumptions (BottomTabBar
safe-area/in-viewport, 56×56 FAB, PhoneNav chrome, tap targets). Primary compat-pass target.
- `apps/pwa/e2e/calendar.spec.ts` — auth-bypass precondition, no-SW precondition, populated/error states.
- `apps/pwa/e2e/lists.spec.ts` — populated/empty states.
- `apps/pwa/e2e/global-setup.ts``/health` readiness poll + deterministic DB reset/seed (shared by
all profiles, unchanged by this phase).
- `apps/pwa/e2e/README.md` — harness run/guardrail docs; update for the new profile.
### Phase context / roadmap
- `.planning/ROADMAP.md` §"Phase 14: Desktop E2E Coverage" — goal, 3 success criteria, pitfalls.
- `.planning/phases/07-mobile-test-harness/07-CONTEXT.md` — original harness decisions to carry forward
(DEV_AUTH_BYPASS not storageState, `serviceWorkers: 'block'`, env baseURL, Vite-only webServer).
- `.planning/phases/08-gitea-ci/08-CONTEXT.md` — how CI runs `pnpm test:e2e`; confirms desktop project
is picked up automatically (only watch desktop-profile runtime/wait in CI).
### CI entry point (no plumbing change expected, but verify)
- `.gitea/workflows/ci.yml` — the harness job that runs the Playwright specs; confirm the new desktop
project runs and gates without a config change beyond runtime/wait budget.
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- **Existing `playwright.config.ts` project array** — add a third `{ name: 'desktop', use: {
...devices['Desktop Chrome'], serviceWorkers: 'block' } }` entry. `serviceWorkers: 'block'`,
env baseURL, and the Vite `webServer` are already shared across projects.
- **`global-setup.ts`** — DB reset/seed is profile-agnostic; reused unchanged for desktop.
### Established Patterns
- **Breakpoint = 767/768px**, driven by `window.matchMedia('(max-width: 767px)')` in
`AppNav.tsx:32`, `BottomTabBar.tsx:24`, `CalendarShell.tsx:75`. Desktop Chrome at 1280px is
unambiguously in the desktop branch.
- **`getByRole('navigation', { name: 'Main navigation' })`** resolves to the **BottomTabBar** on
mobile but the **DesktopNav sidebar** on desktop — same locator, different element, both valid.
- **No strict-mode collision on desktop:** `BottomTabBar.tsx:53-57` returns `null` at ≥768px, so the
sidebar is the *sole* `Main navigation` landmark on desktop. Most nav-visibility/tap-target tests
pass as-authored, just resolving to the sidebar.
### Integration Points — desktop divergences the compat pass must handle
- **BottomTabBar safe-area / "fully in-viewport" tests** (`layout.spec.ts` describe blocks):
bottom bar is `null` on desktop → **skip on desktop**.
- **"New Event FAB meets 56×56px"** (`layout.spec.ts:91`): on desktop the `New Event` name resolves
to the toolbar button (`CalendarShell.tsx:424`), which is not 56×56 → **skip the FAB-geometry test
on desktop**; optionally assert the desktop toolbar button's ≥44px target instead (D-04 parity).
- **"PhoneNav header is visible"** (`layout.spec.ts:76`): `getByText('FamilySync', {exact:true})` also
matches the DesktopNav title (`AppNav.tsx:181`) → likely passes on desktop; verify no second match.
- **Settings button** (`/open settings/i`): present on both PhoneNav and DesktopNav → resolves on both.
- **Tap-target tests scoped to the nav landmark**: desktop sidebar links have `minHeight: 44px`
(`AppNav.tsx:151`) → pass on desktop.
</code_context>
<specifics>
## Specific Ideas
- The gate's whole point is to be real: desktop must be **blocking**, and the specs must be made
deterministic to earn that (D-03). "Make it green by weakening the assertion" is explicitly rejected.
- Mirror Phase 7's self-validation ethos where cheap: a desktop run should fail loudly if the desktop
layout actually regresses, not silently pass because everything was skipped.
</specifics>
<deferred>
## Deferred Ideas
- **Desktop WebKit (Desktop Safari) profile** — considered and declined for this phase (D-06).
Revisit only if a desktop-Safari-specific rendering bug is ever reported.
- **Live desktop event-create round-trip** — still blocked by dev user 1 having no CalDAV calendar
(carried from Phase 7); out of scope here, same as on mobile.
None of the above are blockers — discussion stayed within phase scope.
</deferred>
---
*Phase: 14-Desktop E2E Coverage*
*Context gathered: 2026-06-12*