docs(07): capture phase context
This commit is contained in:
@@ -0,0 +1,103 @@
|
|||||||
|
# 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-08–D-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 (≈L424–425, 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*
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Phase 7: Mobile Test Harness - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-06-10
|
||||||
|
**Phase:** 7-Mobile Test Harness
|
||||||
|
**Areas discussed:** Device profile(s), Test-data strategy, Assertion approach, Stack lifecycle / baseURL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Device profile(s)
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| iPhone only | Single iPhone profile; matches Apple-member UX constraint; fastest, misses Android-Chrome layout | |
|
||||||
|
| iPhone + Pixel | Two-profile matrix covering both ecosystems; ~2x runtime | ✓ |
|
||||||
|
| iPhone + small-Android | iPhone + narrow Android profile to stress tightest viewport | |
|
||||||
|
|
||||||
|
**User's choice:** iPhone + Pixel
|
||||||
|
|
||||||
|
### Follow-up: engine fidelity
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Faithful engines | iPhone → WebKit, Pixel → Chromium; most faithful; adds WebKit to CI image | ✓ |
|
||||||
|
| Chromium-only | Both Chromium, iPhone viewport/UA/touch only; lighter, matches playwright-cli | |
|
||||||
|
|
||||||
|
**User's choice:** Faithful engines
|
||||||
|
**Notes:** Accepts heavier browser image for true WebKit/Chromium rendering fidelity.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Test-data strategy
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Seed DB fixtures | Insert deterministic rows before run; realistic end-to-end render path | |
|
||||||
|
| Mock API routes | Playwright route-fulfill canned JSON; hermetic, bypasses real API | |
|
||||||
|
| Chrome/empty-states only | No population; assert nav/drawers/tap-targets/empty copy; smallest scope | |
|
||||||
|
| Hybrid: seed + empty | Seed DB for populated views + keep empty-state assertions; broadest coverage | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** Hybrid: seed + empty
|
||||||
|
**Notes:** Captured constraint — seed must be deterministic and reset per run (SC #3, repeatable day-over-day); runs in global-setup against MariaDB :3306, targets shared calendar id 10 + lists.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Assertion approach
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Structural + tap-targets | Role/locator + measured box checks (≥44px, no overflow); portable, stable; misses visual drift | |
|
||||||
|
| Both (structural + screenshots) | Add toHaveScreenshot; catches visual regressions but flaky cross-env | |
|
||||||
|
| Screenshots-primary | Lean on visual snapshots; highest flakiness/maintenance | |
|
||||||
|
|
||||||
|
**User's choice:** Other (free text) — "Defer this decision to research and for you to decide as it needs to be robust and low maintenance. I have to imagine this has been done elsewhere before and should be well documented."
|
||||||
|
**Notes:** Marked as research question, not locked. Claude's steer: lead with structural + tap-target measurement; add screenshots only if research finds a non-flaky CI-baseline pattern. Schedule-X widget makes naive pixel snapshots drift-prone.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stack lifecycle / baseURL
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| baseURL + readiness wait | Configurable baseURL, readiness gate; caller owns stack bring-up; matches existing dev stack | ✓ (Claude, per "you decide") |
|
||||||
|
| Playwright webServer | Auto-start vite; can't own multi-container API/DB/Redis stack | (partial — vite only) |
|
||||||
|
| You decide | Pick best fit for SC #4 + local ergonomics | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** You decide
|
||||||
|
**Notes:** Claude's recommendation — baseURL (env-driven) + global-setup readiness gate on /health; caller (operator locally / compose in CI) brings up the stack; optional webServer for vite only with `reuseExistingServer: !CI`; API+MariaDB+Redis stay compose-managed. Satisfies SC #4.
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- **Assertion approach** — deferred to research (robust/low-maintenance, host↔CI portable).
|
||||||
|
- **Stack lifecycle** — "you decide"; recommendation captured above, planner may refine env-var name / webServer wiring.
|
||||||
|
- Spec file location/structure, failure trace/artifact capture, npm-script + Makefile wiring — not discussed; planner's discretion following existing conventions.
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- "Gitea CI — full regression + Docker publish" todo (score 0.6) — belongs to Phase 8, which consumes this harness. Reviewed, not folded.
|
||||||
Reference in New Issue
Block a user