Files
familysync/.planning/phases/14-desktop-e2e-coverage/14-CONTEXT.md
T

8.7 KiB
Raw Blame History

Phase 14: Desktop E2E Coverage - Context

Gathered: 2026-06-12 Status: Ready for planning

## 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.

## 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).

<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>
## 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.
## 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.


Phase: 14-Desktop E2E Coverage Context gathered: 2026-06-12