5.6 KiB
status, phase, source, mode, started, updated
| status | phase | source | mode | started | updated | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| complete | 04-shared-lists-live-sync |
|
playwright-cli (automated, operator-elected) | 2026-06-09T18:39:39Z | 2026-06-09T18:48:06Z |
Current Test
[testing complete]
Tests
1. Cold Start Smoke Test
expected: API /health returns 200, PWA loads, navigating to /lists renders the Lists surface with live data (not an error/blank). result: pass evidence: API /health → {"ok":true,"db":"up"}; PWA served on :5173; /lists rendered empty-state ("No lists yet") with GET /api/lists → 200.
2. Navigate to Lists (bottom tab bar)
expected: Bottom tab bar / desktop nav exposes a "Lists" link; clicking routes to /lists and shows the index. result: pass evidence: Desktop sidebar nav shows Calendar + Lists links; Calendar link routed to /calendar (full calendar rendered), Lists link routed to /lists. (Bottom tab bar is the mobile-width variant of the same nav.)
3. Create a named list (defaults to Shared)
expected: CreateListSheet opens; entering a name + confirming creates the list (default Shared), sheet closes, new card appears. result: pass evidence: "New list" sheet opened with Visibility toggle defaulting to Shared [pressed], Create disabled until named. Created "Groceries" → POST /api/lists → 201; card "Groceries · 0 items · Shared" appeared.
4. Delete a list with confirmation
expected: Delete (X) control opens ListDeleteDialog with clear heading/body; confirm removes card, cancel leaves it. result: pass evidence: Created throwaway "ToDelete"; hover revealed "Delete list: ToDelete"; dialog "Delete list?" with body "'ToDelete' and all its items will be permanently removed." Confirm → DELETE /api/lists/1279 → 200; ToDelete removed, Groceries remained.
5. Open a list and add items
expected: ListDetail shows add-item input; typing + Add inserts into "Active items" with checkbox + drag handle; optimistic. result: pass evidence: Opened /lists/1278 — "Live sync connected" indicator present. Added milk, eggs, bread → all in "Active items" with checkboxes and "Drag to reorder" handles.
6. Check an item — sinks to Completed
expected: Checking moves item into a "Completed (N)" section (D-05); unchecking returns to bottom of Active. result: pass evidence: Checked "milk" → moved into "Completed (1)" collapsible section (checkbox checked); Active showed eggs, bread.
7. Delete an item instantly (no confirm)
expected: Delete control removes item immediately, no confirmation (D-06/D-09 delete-wins). result: pass evidence: Deleted "eggs" → removed instantly, no dialog rendered (snapshot confirmed no dialog/confirm element).
8. Drag to reorder active items
expected: Dragging an item by its handle to a new position persists (survives reload); single-row rank write. result: pass evidence: Dragged "cheese" from bottom to top → order cheese/bread/apples; PATCH /api/list-items → 200; order persisted after full page reload.
9. Drag an item to the very top (collation regression)
expected: Dragging to position 0 persists; dragged item stays first after reload (utf8mb4_bin collation, Plan 04-07). result: pass evidence: Manual pointer drag of "cheese" above the a0-ranked top generated rank "Zz" (uppercase-prefixed). DB-ordered API AND UI both returned cheese FIRST (cheese=Zz, apples=a0, bread=a0V); persisted after reload. Without the collation fix, MariaDB's case-insensitive default would sort 'Zz' after 'a0' and bounce it to the bottom — confirmed fixed end-to-end.
10. Live sync between two members (within seconds)
expected: With two sessions on the same shared list, an edit in A appears in B within seconds, no manual refresh. result: pass evidence: Opened session B (separate browser context) on /lists/1278 — "Live sync connected". Added "butter" in session A → appeared in session B within ~3s with no reload.
11. Live sync survives a brief reconnect
expected: On SSE drop, LiveSyncIndicator reflects reconnecting/disconnected then returns to connected (bounded backoff); edits reconcile. result: pass evidence: (a) Took B offline + added "yogurt" in A → on reconnect, yogurt reconciled into B. (b) Blocked **/api/sse/lists (503) + reloaded B → indicator showed "Reconnecting…"; unblocked + reloaded → returned to "Live sync connected". Bounded-backoff hook also unit-tested (04-06, 8 passing hook tests).
12. Private-list isolation (no cross-leak)
expected: A member's private list and its events are never visible to a member without access (D-04). result: skipped reason: Not drivable via the live UI — the dev-auth bypass injects a single static DEV_USER with no user-switching, so two distinct authenticated members cannot be simulated through the PWA. D-04 isolation is comprehensively proven at the route layer by passing automated tests: T-04-02 (GET excludes another member's private list), the 4 D-04 scoped-SSE tests in 04-06 (no fan-out leak to non-members), and the 04-07 sharee-403 tests. Re-confirm during the live multi-user Pangolin/Authelia smoke (deployment gate).
Summary
total: 12 passed: 11 issues: 0 pending: 0 skipped: 1 blocked: 0
Gaps
[none — all functional tests passed; test 12 deferred to deployment-time multi-user smoke, already covered by automated route-layer D-04 tests]
Notes
- Known non-blocking stub observed: ListDetail header renders "List" rather than the list name (carried from Plans 04-04/04-05; fetchListItems returns items only). Does not affect any LIST-01..04 behavior. Tracked in plan summaries.
- Console: only a favicon.ico 404 (harmless); no application errors during any flow.