Compare commits
2
Commits
f75bc4239f
...
cf48fa8e1b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf48fa8e1b | ||
|
|
f9fc7bbda2 |
@@ -276,7 +276,7 @@ Plans:
|
||||
| 11. Per-Event Reminders | v1.1 | 0/? | Not started | - |
|
||||
| 12. Initial Setup Wizard | v1.1 | 0/? | Not started | - |
|
||||
| 13. Real Lint Gate (ESLint) | v1.1 | 3/3 | Complete | 2026-06-12 |
|
||||
| 14. Desktop E2E Coverage | v1.1 | 1/1 | Complete | 2026-06-12 |
|
||||
| 14. Desktop E2E Coverage | v1.1 | 1/1 | Complete | 2026-06-12 |
|
||||
|
||||
## Backlog
|
||||
|
||||
|
||||
+10
-9
@@ -4,14 +4,14 @@ milestone: v1.1
|
||||
milestone_name: Operability & Polish
|
||||
status: executing
|
||||
stopped_at: Phase 14 context gathered
|
||||
last_updated: "2026-06-12T12:14:45.983Z"
|
||||
last_activity: 2026-06-12 -- Phase 14 execution started
|
||||
last_updated: "2026-06-12T13:10:04.656Z"
|
||||
last_activity: 2026-06-12
|
||||
progress:
|
||||
total_phases: 18
|
||||
completed_phases: 3
|
||||
completed_phases: 4
|
||||
total_plans: 12
|
||||
completed_plans: 11
|
||||
percent: 17
|
||||
completed_plans: 12
|
||||
percent: 22
|
||||
---
|
||||
|
||||
# Project State
|
||||
@@ -25,16 +25,16 @@ See: .planning/PROJECT.md (updated 2026-06-10)
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 14 (desktop-e2e-coverage) — EXECUTING
|
||||
Plan: 1 of 1
|
||||
Phase: 999.1
|
||||
Plan: Not started
|
||||
Status: Executing Phase 14
|
||||
Last activity: 2026-06-12 -- Phase 14 execution started
|
||||
Last activity: 2026-06-12
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
**Velocity:**
|
||||
|
||||
- Total plans completed: 24
|
||||
- Total plans completed: 25
|
||||
- Average duration: -
|
||||
- Total execution time: 0 hours
|
||||
|
||||
@@ -46,6 +46,7 @@ Last activity: 2026-06-12 -- Phase 14 execution started
|
||||
| 03 | 12 | - | - |
|
||||
| 07 | 4 | - | - |
|
||||
| 13 | 3 | - | - |
|
||||
| 14 | 1 | - | - |
|
||||
|
||||
**Recent Trend:**
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
phase: 14-desktop-e2e-coverage
|
||||
verified: 2026-06-12T00:00:00Z
|
||||
status: passed
|
||||
score: 5/5 must-haves verified
|
||||
overrides_applied: 0
|
||||
---
|
||||
|
||||
# Phase 14: Desktop E2E Coverage Verification Report
|
||||
|
||||
**Phase Goal:** The Phase 8 regression gate exercises the desktop layout and flows, not just mobile. A `desktop` Playwright project (`devices['Desktop Chrome']`, no touch, wide viewport) is added to `apps/pwa/playwright.config.ts`, and the existing mobile-authored specs are reviewed/adjusted (or appropriately skipped) so `pnpm test:e2e` passes on a no-touch desktop viewport as well as the `iphone`/`pixel` profiles.
|
||||
**Verified:** 2026-06-12
|
||||
**Status:** passed
|
||||
**Re-verification:** No — initial verification
|
||||
|
||||
---
|
||||
|
||||
## Goal Achievement
|
||||
|
||||
### Observable Truths
|
||||
|
||||
| # | Truth | Status | Evidence |
|
||||
|---|-------|--------|----------|
|
||||
| 1 | A `desktop` Playwright project (Desktop Chrome, 1280×720, no hasTouch) exists in playwright.config.ts (SC-1, D-06) | VERIFIED | `name: 'desktop'` at line 58; `...devices['Desktop Chrome']` at line 60; `serviceWorkers: 'block'` at line 61; no `baseURL` inside the desktop project block (inherited from top-level `use`); comment explicitly states "no hasTouch (D-06)" |
|
||||
| 2 | `pnpm --filter @familysync/pwa test:e2e` exits 0 on all three projects: iphone, pixel, desktop (SC-2) | VERIFIED | CI run #32 (PR #10 → main): harness job ran `pnpm --filter @familysync/pwa test:e2e --reporter=list,html` with no `--project` filter — all three projects execute; SUMMARY records 85 passed / 5 skipped / 0 failed; commits d3bc696, 2903599, bfc49d1 are present in git history |
|
||||
| 3 | The two mobile-only assertions (BottomTabBar safe-area in-viewport, 56×56 FAB geometry) are skipped on desktop only, not deleted, and still run on iphone/pixel (SC-2, D-01, D-02) | VERIFIED | `grep -c "testInfo.project.name === 'desktop'" layout.spec.ts` == 3 (three skip guards: line 66, 99, 161); `toBeGreaterThanOrEqual(56)` still present at lines 107–108; `toBeGreaterThanOrEqual(44)` still present at lines 50–51, 59–60, 94–95, 127, 147–148, 156–157, 248; no test body removed |
|
||||
| 4 | Cross-cutting tests (no-overflow, nav-landmark visible, tap targets ≥44px, populated/empty/error states) run unchanged on desktop (SC-2, D-04); D-04 parity (New Event toolbar button ≥44px) asserting only on desktop | VERIFIED | D-04 parity test at lines 114–128 guarded by `testInfo.project.name !== 'desktop'` (confirmed by grep count == 1); overflow, nav-landmark, calendar/lists populated/error/empty state tests have no project-name guards and run on all three profiles; `calendar.spec.ts` and `lists.spec.ts` contain no structural test changes |
|
||||
| 5 | The desktop gate is blocking — no `continue-on-error` carve-out (SC-3, D-03) | VERIFIED | `grep "continue-on-error" .gitea/workflows/ci.yml` returns nothing; harness step runs `pnpm --filter @familysync/pwa test:e2e` (all projects) with no isolation or continue-on-error; Chromium engine already installed via `playwright install --with-deps webkit chromium` (line 242); CI step name updated to name all three profiles (line 255, cosmetic only) |
|
||||
|
||||
**Score:** 5/5 truths verified
|
||||
|
||||
---
|
||||
|
||||
### Required Artifacts
|
||||
|
||||
| Artifact | Expected | Status | Details |
|
||||
|----------|----------|--------|---------|
|
||||
| `apps/pwa/playwright.config.ts` | desktop project entry mirroring iphone/pixel | VERIFIED | `name: 'desktop'`, `...devices['Desktop Chrome']`, `serviceWorkers: 'block'`; no baseURL in project block; header jsdoc lists three profiles |
|
||||
| `apps/pwa/e2e/layout.spec.ts` | desktop-skip guards on two mobile-only tests + D-04 parity assertion | VERIFIED | Exactly 3 `test.skip(testInfo.project.name === 'desktop', ...)` guards; 1 `test.skip(testInfo.project.name !== 'desktop', ...)` parity guard; all prior mobile assertions intact |
|
||||
| `apps/pwa/e2e/README.md` | harness docs listing the desktop profile | VERIFIED | Line 1 preamble mentions "Desktop Chrome (1280×720)"; `--project=desktop` example at line 42; run commands block names all three profiles |
|
||||
|
||||
---
|
||||
|
||||
### Key Link Verification
|
||||
|
||||
| From | To | Via | Status | Details |
|
||||
|------|-----|-----|--------|---------|
|
||||
| `apps/pwa/playwright.config.ts` | `devices['Desktop Chrome']` | spread into desktop project `use` block | VERIFIED | Line 60: `...devices['Desktop Chrome']` |
|
||||
| `apps/pwa/e2e/layout.spec.ts` | `testInfo.project.name` | `test.skip` first-statement guard keyed on `=== 'desktop'` | VERIFIED | Three guards at lines 66–69, 99–102, 161–164; all use first-statement form inside `async ({ page }, testInfo)` |
|
||||
| CI harness | all three projects | `pnpm --filter @familysync/pwa test:e2e` with no `--project` filter | VERIFIED | `.gitea/workflows/ci.yml` line 293; picks up `desktop` automatically |
|
||||
|
||||
---
|
||||
|
||||
### Data-Flow Trace (Level 4)
|
||||
|
||||
Not applicable. Phase produces only test-harness artifacts — no runtime components rendering dynamic data.
|
||||
|
||||
---
|
||||
|
||||
### Behavioral Spot-Checks
|
||||
|
||||
| Behavior | Command | Result | Status |
|
||||
|----------|---------|--------|--------|
|
||||
| desktop project resolves in Playwright | `grep -c "name: 'desktop'" apps/pwa/playwright.config.ts` | 1 | PASS |
|
||||
| Exactly 3 desktop skip guards | `grep -c "testInfo.project.name === 'desktop'" apps/pwa/e2e/layout.spec.ts` | 3 | PASS |
|
||||
| D-04 parity guard present | `grep -c "testInfo.project.name !== 'desktop'" apps/pwa/e2e/layout.spec.ts` | 1 | PASS |
|
||||
| Mobile 56px FAB assertions intact | `grep "toBeGreaterThanOrEqual(56)" apps/pwa/e2e/layout.spec.ts` | 2 matches (lines 107–108) | PASS |
|
||||
| No `desktop.spec.ts` created (D-01) | `ls apps/pwa/e2e/desktop.spec.ts` | NOT FOUND | PASS |
|
||||
| No `continue-on-error` in CI harness | `grep "continue-on-error" .gitea/workflows/ci.yml` | no output | PASS |
|
||||
| Commits from SUMMARY exist | `git log --oneline d3bc696 2903599 bfc49d1` | all three found in history | PASS |
|
||||
|
||||
---
|
||||
|
||||
### Probe Execution
|
||||
|
||||
No probes declared in PLAN or found at `scripts/*/tests/probe-*.sh`. Skipped.
|
||||
|
||||
---
|
||||
|
||||
### Requirements Coverage
|
||||
|
||||
| Requirement | Description | Status | Evidence |
|
||||
|-------------|-------------|--------|---------|
|
||||
| SC-1 | `desktop` project (Desktop Chrome, 1280×720, no `hasTouch`) exists in `playwright.config.ts` | SATISFIED | Verified at `playwright.config.ts:56–63` |
|
||||
| SC-2 | Existing e2e specs pass (or justifiably skipped) on desktop; `pnpm test:e2e` green on all three projects | SATISFIED | 3 mobile-geometry tests desktop-skipped with factual reasons; D-04 parity added; CI run #32 green |
|
||||
| SC-3 | Desktop gate is blocking in CI (no `continue-on-error`), runs automatically, specs deterministic | SATISFIED | No `continue-on-error` in CI yml; harness runs all projects via single `test:e2e` invocation with no filter |
|
||||
|
||||
---
|
||||
|
||||
### Anti-Patterns Found
|
||||
|
||||
| File | Pattern | Severity | Impact |
|
||||
|------|---------|----------|--------|
|
||||
| `apps/pwa/e2e/layout.spec.ts:83–96` | `PhoneNav header is visible` and `PhoneNav settings button` tests run unguarded on desktop, silently re-targeting DesktopNav elements (WR-01 from code review) | INFO | Tests pass by coincidence on desktop; a PhoneNav-specific regression would not be caught on the desktop profile. Not a blocker — both tests still pass and the phase goal (desktop gate green) is achieved. Flagged in 14-REVIEW.md. |
|
||||
| `apps/pwa/e2e/calendar.spec.ts:16` / `lists.spec.ts:19` | Header comment claims "all tests pass unchanged" without qualifying the month-grid/DesktopNav view divergence on desktop (WR-02, WR-03 from code review) | INFO | Comment is misleading but not a correctness failure. No test is broken. |
|
||||
|
||||
No TBD / FIXME / XXX markers found in any phase-modified file.
|
||||
|
||||
---
|
||||
|
||||
### Human Verification Required
|
||||
|
||||
None. All must-haves are verifiable programmatically. CI evidence (PR #10, run #32) confirms full-suite green. No visual, real-time, or device-only checks are required to confirm the phase goal.
|
||||
|
||||
---
|
||||
|
||||
## Gaps Summary
|
||||
|
||||
No gaps. All five must-have truths are verified by direct codebase inspection:
|
||||
|
||||
- `playwright.config.ts` contains the correct `desktop` project entry with all required properties.
|
||||
- `layout.spec.ts` has exactly the right guard count (3 desktop-skip, 1 desktop-only parity) and all prior mobile assertions are intact.
|
||||
- No `desktop.spec.ts` was created.
|
||||
- The CI harness runs all three projects without `continue-on-error`.
|
||||
- README and spec headers document the desktop profile.
|
||||
|
||||
The code review (14-REVIEW.md) identified three warnings (WR-01 misleading test names, WR-02 month-grid claim, WR-03 comment accuracy) and three info items (IN-01 serviceWorkers hoisting, IN-02 missing auth-wait in parity test, IN-03 implicit viewport assumption). None of these affect the phase goal or the correctness of the desktop gate. They are documentation/quality items for a follow-up if desired.
|
||||
|
||||
---
|
||||
|
||||
_Verified: 2026-06-12_
|
||||
_Verifier: Claude (gsd-verifier)_
|
||||
@@ -0,0 +1,94 @@
|
||||
---
|
||||
phase: 14-desktop-e2e-coverage
|
||||
reviewed: 2026-06-12T00:00:00Z
|
||||
depth: standard
|
||||
files_reviewed: 6
|
||||
files_reviewed_list:
|
||||
- apps/pwa/playwright.config.ts
|
||||
- apps/pwa/e2e/layout.spec.ts
|
||||
- apps/pwa/e2e/calendar.spec.ts
|
||||
- apps/pwa/e2e/lists.spec.ts
|
||||
- apps/pwa/e2e/README.md
|
||||
- .gitea/workflows/ci.yml
|
||||
findings:
|
||||
critical: 0
|
||||
warning: 3
|
||||
info: 3
|
||||
total: 6
|
||||
status: issues_found
|
||||
---
|
||||
|
||||
# Phase 14: Code Review Report
|
||||
|
||||
**Reviewed:** 2026-06-12
|
||||
**Depth:** standard
|
||||
**Files Reviewed:** 6
|
||||
**Status:** issues_found
|
||||
|
||||
## Summary
|
||||
|
||||
Phase 14 adds a third Playwright project (`desktop` — Desktop Chrome, 1280×720, no `hasTouch`) and makes the existing mobile-authored e2e specs green on desktop. The diff is test-harness-only — no runtime/app code changed. I verified the load-bearing source assumptions encoded in the new skip guards against the actual components:
|
||||
|
||||
- **Skip guards are correct.** On desktop (≥768px) `AppNav` renders `DesktopNav` with the sole `<nav aria-label="Main navigation">` (`AppNav.tsx:168`), and `BottomTabBar` returns `null` (`BottomTabBar.tsx:56`). There is no strict-mode collision and the safe-area-inset bottom-edge assertion is genuinely meaningless for a left sidebar — the two `BottomTabBar is fully in-viewport` skips are right.
|
||||
- **FAB skip / desktop-parity test are consistent.** On desktop the only `button` with accessible name "New Event" is the toolbar button (`CalendarShell.tsx:436-457`, text "New Event", `minHeight: '44px'`). The FAB is gated behind `phone &&` (`CalendarShell.tsx:464`), so the 56×56 FAB assertion correctly skips and the new ≥44px parity test (`testInfo.project.name !== 'desktop'` inverse-guard) correctly runs only on desktop. The two guards target the exact same locator — internally consistent.
|
||||
- **No mobile assertion was weakened or deleted.** `calendar.spec.ts` and `lists.spec.ts` changes are comment-only. `layout.spec.ts` only adds guards + one new test; every prior mobile assertion is intact. The CI workflow change is comment-only (step name + comment), the `desktop` project runs automatically because the harness invokes `playwright test` with no `--project` filter.
|
||||
|
||||
Findings below are quality/determinism concerns, not correctness blockers. The harness logic is sound.
|
||||
|
||||
## Warnings
|
||||
|
||||
### WR-01: Two "PhoneNav" tests silently re-target DesktopNav on desktop and no longer test what their names claim
|
||||
|
||||
**File:** `apps/pwa/e2e/layout.spec.ts:83-96`
|
||||
**Issue:** `PhoneNav header is visible (Rule 3)` and `PhoneNav settings button meets 44×44px (Rule 1)` are NOT guarded, so they run on the `desktop` project. On desktop `PhoneNav` is never rendered (`AppNav.tsx:34` returns `DesktopNav` at ≥768px). The tests pass only by coincidence:
|
||||
- `getByText('FamilySync', { exact: true })` matches the `DesktopNav` sidebar title (`AppNav.tsx:181`) instead of the PhoneNav header.
|
||||
- `getByRole('button', { name: /open settings/i })` matches the `DesktopNav` avatar button (`AppNav.tsx:220-222`, `minHeight: '44px'`) instead of the PhoneNav settings button.
|
||||
|
||||
This is misleading green: a future regression that breaks PhoneNav specifically would still pass on desktop, and the test name asserts a component that isn't on screen. The phase scope ("right tests skipped, no over/under-skipping") implies these mobile-named geometry tests should either be desktop-skipped (like the FAB) or renamed to reflect that on desktop they validate the DesktopNav equivalent.
|
||||
**Fix:** Either guard them mobile-only and add explicit DesktopNav counterparts, e.g.:
|
||||
```ts
|
||||
test('PhoneNav header is visible (Rule 3)', async ({ page }, testInfo) => {
|
||||
test.skip(testInfo.project.name === 'desktop',
|
||||
'PhoneNav is not rendered at ≥768px; DesktopNav renders the FamilySync title instead');
|
||||
// ...
|
||||
});
|
||||
```
|
||||
or rename to "App header/title is visible" and "Settings affordance meets 44×44px" so the assertion is honest across all three profiles.
|
||||
|
||||
### WR-02: calendar.spec "all tests pass unchanged" relies on an untested Schedule-X view (month-grid) on desktop
|
||||
|
||||
**File:** `apps/pwa/e2e/calendar.spec.ts:16`, `apps/pwa/e2e/calendar.spec.ts:92-101`
|
||||
**Issue:** The header comment claims desktop runs "all tests pass unchanged", but the desktop default Schedule-X view differs from mobile: `readPersistedView()` returns `month-grid` for ≥768px vs `month-agenda` for ≤767px (`apps/pwa/src/store/calendarStore.ts:14-15,119-120`). The `seeded event "Seeded Test Event" is rendered (DB→UI proof)` test asserts `getByText('Seeded Test Event').first()` is visible — on desktop this now exercises month-grid rendering that the iphone/pixel profiles never covered. In month-grid, an event title can be collapsed into a "+N more" overflow affordance when a day cell is crowded. With a single seeded event today this won't trigger, so the risk is low, but the claim "unchanged" understates that desktop adds a new rendering path. If global-setup is ever extended to seed multiple same-day events, this assertion could flake/fail on desktop only.
|
||||
**Fix:** Note the view divergence in the comment, and make the assertion view-robust if multi-event seeds are anticipated — e.g. assert the event is reachable, falling back to an explicit week/day view switch, or pin the desktop test to a deterministic view. At minimum, change the comment to "all tests pass; desktop renders month-grid (mobile renders month-agenda)".
|
||||
|
||||
### WR-03: lists.spec / calendar.spec "all tests pass unchanged" claim is unverified by the diff and contradicted by view/landmark divergence
|
||||
|
||||
**File:** `apps/pwa/e2e/lists.spec.ts:19`, `apps/pwa/e2e/calendar.spec.ts:16`
|
||||
**Issue:** Both comment headers added by this phase assert "(all tests pass unchanged)" for the desktop profile. The lists `at least one list item is present` test (`lists.spec.ts:43-48`) and `seeded "E2E Grocery List" card` test depend on `ListsIndex.tsx:152` `role="list"` + `ListCard.tsx:52` `role="listitem"`, which are viewport-independent — those are fine. But the blanket "unchanged" wording is an unverifiable assertion baked into source comments; it papers over WR-01 (PhoneNav tests retarget) and WR-02 (month-grid). Comments that assert test outcomes drift out of date and mislead future readers into trusting desktop coverage they don't have.
|
||||
**Fix:** Replace "all tests pass unchanged" with a factual statement of what desktop exercises (e.g. "desktop renders DesktopNav sidebar + month-grid; mobile-geometry tests are skipped, see layout.spec.ts"). Keep outcome claims out of source comments — let the CI run be the source of truth.
|
||||
|
||||
## Info
|
||||
|
||||
### IN-01: `serviceWorkers: 'block'` is duplicated across all three projects instead of hoisted to shared `use`
|
||||
|
||||
**File:** `apps/pwa/playwright.config.ts:45,53,62`
|
||||
**Issue:** Every project repeats `serviceWorkers: 'block'`. The config comment (`line 6`) states it applies to all profiles, so it is a global invariant, not a per-device override. Repeating it invites a future profile being added without it (silent SW-block regression).
|
||||
**Fix:** Hoist `serviceWorkers: 'block'` into the top-level `use` block (line 28-34) and drop it from each project. Per-project `use` only needs the device descriptor spread.
|
||||
|
||||
### IN-02: New desktop parity test has no explicit auth/mount wait before locating the toolbar button
|
||||
|
||||
**File:** `apps/pwa/e2e/layout.spec.ts:114-128`
|
||||
**Issue:** The describe-level `beforeEach` (`layout.spec.ts:32-34`) only does `page.goto('/calendar')` with no `await expect(nav).toBeVisible()` gate (unlike the calendar/lists specs which wait for the nav landmark). The new test relies entirely on `boundingBox()` auto-waiting for the toolbar button to mount after auth + CalendarShell render. This works because Playwright retries, but it's inconsistent with the explicit auth-wait pattern used in `calendar.spec.ts:79` and `lists.spec.ts:33`, and a slow desktop mount could eat into the default timeout.
|
||||
**Fix:** Add `await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();` at the top of the new test (or in a desktop-scoped beforeEach) to gate on auth before measuring, matching the established pattern.
|
||||
|
||||
### IN-03: Desktop project lacks an explicit viewport assertion / pin
|
||||
|
||||
**File:** `apps/pwa/playwright.config.ts:56-63`
|
||||
**Issue:** The `desktop` project relies entirely on `devices['Desktop Chrome']`'s bundled 1280×720 viewport. The spec comments hard-code "1280×720" in three files (`layout.spec.ts:13`, `calendar.spec.ts:16`, `lists.spec.ts:19`). If Playwright's `Desktop Chrome` descriptor viewport ever changes across a version bump, the comments silently lie and the ≥768px breakpoint assumptions could (in extreme cases) break with no guard. Low risk — 1280×720 is stable — but the breakpoint dependency (≥768px) is implicit.
|
||||
**Fix:** Optionally pin `viewport: { width: 1280, height: 720 }` explicitly in the desktop project `use` so the ≥768px DesktopNav assumption is self-documenting and version-stable.
|
||||
|
||||
---
|
||||
|
||||
_Reviewed: 2026-06-12_
|
||||
_Reviewer: Claude (gsd-code-reviewer)_
|
||||
_Depth: standard_
|
||||
Reference in New Issue
Block a user