Files
familysync/.planning/phases/07-mobile-test-harness/07-CONTEXT.md
T

104 lines
8.4 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 7: Mobile Test Harness - Context
**Gathered:** 2026-06-10
**Status:** Ready for planning
<domain>
## Phase Boundary
Deliver an automated, mobile-emulated, authenticated Playwright harness that drives the FamilySync PWA against the host-side dev stack, so mobile-only layout / tap-target / flow defects are caught automatically rather than only by the operator on real devices. The same specs are the artifact Phase 8 (Gitea CI) runs as its PR UI-regression step.
**In scope:** mobile-emulated browser driving (`@playwright/test`, new dev dep in `apps/pwa`), authenticated via `DEV_AUTH_BYPASS`, structured to run headlessly in CI against a stack the runner brings up.
**Out of scope (stays a human/device gate):** real production-service-worker behavior, iOS-Safari standalone-PWA behavior (Home-Screen install, standalone OIDC redirect, iOS push), live event-create against Fastmail (dev-bypass user 1 has no CalDAV credential / calendars). No backend changes.
</domain>
<decisions>
## Implementation Decisions
### Auth & Service Worker (locked by ROADMAP / PITFALLS — not re-discussed)
- **D-01:** Auth via `DEV_AUTH_BYPASS=true` on the host-side dev stack — **never** a checked-in `storage-state.json` with an expiring session cookie (Pitfall 14). No Authelia/OIDC mocking. Dev-bypass resolves to Dev User id 1.
- **D-02:** Playwright context uses `serviceWorkers: 'block'` so the PWA's `injectManifest` SW (`sw.js`, `registerType: 'autoUpdate'`) cannot intercept requests / return stale cached responses (Pitfall 15). Verify the trace shows no SW-sourced responses.
### Device Emulation
- **D-03:** Run a **two-profile matrix: iPhone + Pixel** — covers both household ecosystems (Apple + Android/Fastmail). The iPhone profile satisfies the hard non-technical-Apple-member UX constraint; Pixel covers Chrome-viewport defects.
- **D-04:** Use **faithful browser engines** per profile: iPhone → **WebKit**, Pixel → **Chromium**. Adds a WebKit browser to the harness/CI image. (Note: this exceeds the existing global `playwright-cli` Chromium tooling — the harness brings its own `@playwright/test` browsers.) SW-block + dev-bypass apply to both profiles.
### Test Data
- **D-05:** **Hybrid** — seed deterministic DB fixtures for populated views **and** keep explicit empty-state assertions. Dev-bypass user 1 natively has no calendars (calendar/list views render empty, live create 422s), so populated coverage requires seeding.
- **D-06:** Seeding is **deterministic and reset per run** (truncate/reset → insert, not insert-if-absent) to guarantee repeatable day-over-day results with no stale state (SC #3). Seed onto the shared calendar (id 10, per prior project memory) + list items so user 1's views render populated.
- **D-07:** Seeding runs in **global-setup** against the dev MariaDB (already port-bound on 3306 via `docker-compose.dev.yml`); teardown/reset keeps runs idempotent.
### Stack Lifecycle / Connection
- **D-08:** Harness targets a **configurable `baseURL`** (env-driven: operator's vite dev server locally, CI service host in Phase 8) with a **readiness gate in global-setup** (wait on `/health` before any spec; mirrors the PITFALLS CI-readiness guidance to avoid flaky ECONNREFUSED).
- **D-09:** **Stack bring-up is the caller's responsibility** — operator's already-running dev stack locally, compose orchestration in Phase 8 CI. The harness never depends on a pre-running stack; it waits for one. Satisfies SC #4.
- **D-10:** Optionally use Playwright `webServer` for **vite only** with `reuseExistingServer: !process.env.CI` (reuse the operator's `pnpm dev` locally, start vite fresh in CI). The API + MariaDB + Redis always stay compose-managed — `webServer` cannot own a multi-container stack.
### Claude's Discretion
- **Assertion approach (D-08-area) — deferred to research.** User wants a robust, low-maintenance, host↔CI-portable pattern and expects this is well-documented prior art. **Steer:** lead with structural / role-based locator assertions + explicit tap-target measurements (computed box ≥ 44px, no horizontal overflow, visibility/position) which are stable across environments. Add `toHaveScreenshot` visual snapshots **only** if research finds a well-established way to keep them non-flaky across host↔CI rendering (CI-generated baselines + tolerance config); otherwise omit screenshots. The Schedule-X calendar widget makes naive pixel snapshots especially drift-prone — weigh that heavily.
- **Stack lifecycle (D-08D-10):** user said "you decide" — decisions above are Claude's recommendation; planner may refine the exact env-var name and webServer wiring.
- Spec file location/structure, trace/artifact capture on failure, and npm-script + Makefile wiring were not discussed — planner's discretion (follow existing conventions: `apps/pwa`, pnpm filters, Makefile-first per global instructions).
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### Phase scope & requirements
- `.planning/ROADMAP.md` § "Phase 7: Mobile Test Harness" — goal, success criteria (4), phase-owned pitfalls, dependency notes.
- `.planning/REQUIREMENTS.md` — TEST-01 (mobile-emulated viewport), TEST-02 (DEV_AUTH_BYPASS auth, dev-build scope, consumed by Phase 8 CI).
### Pitfalls this phase owns (MUST read — they lock D-01/D-02)
- `.planning/research/PITFALLS.md` § "Pitfall 14: Playwright Authed-Mobile Harness Reusing a Stale storage-state" (≈L354) — why `DEV_AUTH_BYPASS`, not storage-state.
- `.planning/research/PITFALLS.md` § "Pitfall 15: Production Service Worker Intercepting Playwright Requests" (≈L375) — `serviceWorkers: 'block'`, verify trace has no SW-sourced responses.
- `.planning/research/PITFALLS.md` quick-reference rows (≈L424425, L491) and the CI-readiness-wait row (≈L409) — readiness gate before specs.
### Codebase conventions
- `.planning/codebase/TESTING.md` — current Vitest setup, test locations, the "E2E not implemented; playwright-cli skill used for smoke tests" gap this phase fills.
- `apps/pwa/vite.config.ts` — vite dev-server proxy (`/api`, `/health`, `/callback` → :3000), `injectManifest` SW config (the SW that D-02 blocks).
- `docker-compose.dev.yml` — dev override exposing MariaDB :3306 / Redis :6379, API `dev` target. The stack the harness targets.
- Project `CLAUDE.md` § "Browser-based verification" — playwright-cli is global Chromium; `@playwright/test` is NOT yet a repo dep (this phase adds it to `apps/pwa`).
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- `DEV_AUTH_BYPASS` already wired across the API (`apps/api/src/auth/devBypass.ts`, `apps/api/src/index.ts`, route handlers) and used in API tests — the harness rides the existing bypass, no new auth code.
- Shared calendar id 10 + dev MariaDB on :3306 (per prior project memory `dev-data-user1-no-calendars` / `dev-stack-bringup`) — the seed target.
- Existing `apps/pwa` Vitest config + test conventions to mirror for harness file layout/naming (note: Playwright specs are typically `*.spec.ts`, distinct from Vitest `*.test.ts` globs — keep them separate so runners don't collide).
### Established Patterns
- Vite dev server proxies `/api`, `/health`, `/callback` to the API on :3000 — `baseURL` points at the vite origin; readiness gate hits proxied `/health`.
- Dev API `dev` target needs its own build (dist can be stale, per prior memory) — relevant when CI brings up the stack.
### Integration Points
- Phase 8 (Gitea CI) consumes these specs as its PR UI-regression step against a CI-brought-up dev stack — keep the harness stack-agnostic via `baseURL` + readiness gate (D-08/D-09).
</code_context>
<specifics>
## Specific Ideas
- User explicitly wants the assertion strategy to be **robust and low-maintenance**, grounded in established/documented prior art rather than a bespoke approach — flagged as the primary research question.
- Faithful WebKit-for-iPhone fidelity was a deliberate choice over Chromium-only emulation, accepting the heavier browser image.
</specifics>
<deferred>
## Deferred Ideas
### Reviewed Todos (not folded)
- **"Gitea CI — full regression on PR to main + build/publish Docker image"** (`.planning/todos/2026-06-10-gitea-ci-regression-and-docker-publish.md`, match score 0.6) — belongs to **Phase 8 (Gitea CI)**, which *consumes* this harness. Not folded; Phase 7 only produces CI-runnable specs, it does not own the CI pipeline.
</deferred>
---
*Phase: 7-Mobile Test Harness*
*Context gathered: 2026-06-10*