docs(BACKLOG): file findings from e2e expansion
Some checks failed
Test / vitest (push) Successful in 11m4s
Test / playwright (push) Failing after 9m59s
Test / visual (push) Failing after 9m20s
Test / Notify on failure (push) Successful in 2s

A11y bug: /board contrast violations (since fixed via --text-faint).
Wave-Slack: /api/auth/member missing slackInvited (fixed), markSlackInvited
non-reactive (fixed), deprecated slackInviteStatus serialization (fixed),
spec-vs-UI wave-language mismatch.
Known gotchas: /admin/series-management Delete is a no-op for empty
series; past-deadline and sold-out events render identically.
Simplify follow-ups: STATUS_LABELS dedup completed.
E2e infrastructure gaps: other email routes still send live in dev,
no dev seeder for arbitrary member status, SSR useFetch blocks
page.route mocking, self-cancel paid registrations not e2e-tested,
visual snapshot regen process.
This commit is contained in:
Jennie Robinson Faber 2026-04-30 22:26:38 +01:00
parent 593b1238f9
commit ba84429917

View file

@ -47,12 +47,15 @@ Membership status is being decoupled from payment status. Copy + UI gates alread
- **Admin edit does not sync Helcim `recurringAmount`.** `/admin/members/[id]` PUT writes `contributionAmount` direct to Mongo by design. Admins must PATCH Helcim manually. The admin form already shows an `--ember`-bordered notice (commit `e756170`); a real sync flow is a future enhancement. - **Admin edit does not sync Helcim `recurringAmount`.** `/admin/members/[id]` PUT writes `contributionAmount` direct to Mongo by design. Admins must PATCH Helcim manually. The admin form already shows an `--ember`-bordered notice (commit `e756170`); a real sync flow is a future enhancement.
- **Cadence switch rejected on active subscriptions.** `server/api/members/update-contribution.post.js:206` refuses cadence changes mid-subscription with a TODO comment pointing here. No UI toggle exists on `/member/account`. Adding cadence switch requires a Helcim subscription replacement flow, not a plain update. - **Cadence switch rejected on active subscriptions.** `server/api/members/update-contribution.post.js:206` refuses cadence changes mid-subscription with a TODO comment pointing here. No UI toggle exists on `/member/account`. Adding cadence switch requires a Helcim subscription replacement flow, not a plain update.
- **S2 test fixture id/slug mismatch (local dev only).** Seeded S2 series has `id: 'test-s2-drop-in-allowed'` but `slug: 'test-s2-drop-in-allowed-series'`. Doesn't affect prod — fix the seed script if anyone re-runs fixtures. - **S2 test fixture id/slug mismatch (local dev only).** Seeded S2 series has `id: 'test-s2-drop-in-allowed'` but `slug: 'test-s2-drop-in-allowed-series'`. Doesn't affect prod — fix the seed script if anyone re-runs fixtures.
- **`/admin/series-management` "Delete" button doesn't actually delete.** Click handler iterates events to PUT-unlink each from the series, never calls `DELETE /api/admin/series/:id`. For an empty series the button is a no-op; for a series with events it just orphans them. Either rename to "Unlink events" or add the actual DELETE call. Surfaced by `e2e/admin-series.spec.js` (delete test skipped). Flagged 2026-04-30.
- **Past-deadline events and sold-out events render identically.** `EventTicketPurchase.vue` falls through to "Event Sold Out" panel for both `tickets.available.reason === 'Registration deadline has passed'` and zero-stock cases. If "Registration closed" is meant to read differently from "Sold out," add a distinct branch. Flagged 2026-04-30 (no e2e written — gated on this UX decision).
--- ---
## Accessibility / a11y ## Accessibility / a11y
- [ ] **Button minimum target size.** Site-wide `.btn` renders ~35px tall. WCAG AA 2.5.8 (24×24) passes; AAA 2.5.5 (44×44) fails. Bumping padding affects every button — design call, not a drop-in fix. Flagged 2026-04-11. - [ ] **Button minimum target size.** Site-wide `.btn` renders ~35px tall. WCAG AA 2.5.8 (24×24) passes; AAA 2.5.5 (44×44) fails. Bumping padding affects every button — design call, not a drop-in fix. Flagged 2026-04-11.
- [ ] **`/board` color-contrast violations (WCAG AA).** `.block-label` ("Offering" tag) and `.slack-handle` use `#746a58` on `#e8dfc8` → 4.01:1; AA needs 4.5:1 for small text. Surfaced by `e2e/a11y.spec.js` (the `/board` route fails; test is intentionally left red until fixed). Likely a single CSS variable adjustment. Flagged 2026-04-30.
--- ---
@ -67,7 +70,11 @@ Membership status is being decoupled from payment status. Copy + UI gates alread
## Wave-Slack pilot follow-ups ## Wave-Slack pilot follow-ups
- [ ] **E2E coverage for `e2e/wave-slack-onboarding.spec.js`.** 16 scaffolded tests, all `.skip`ed with TODOs. Filling them in needs fixture work the spec didn't scope. Test 7.8 (final copy match) and 6.9 (sortable column / "no Slack yet" filter) gated on Open Questions in the test plan. Defer until pilot wraps unless a regression surfaces. - [ ] **`/api/auth/member` doesn't return `slackInvited`.** Dashboard's Slack-coming note is gated on `memberData.slackInvited`, which is always `undefined` client-side, so the note shows for *every* active member regardless of state. Real bug. Add `slackInvited` (and `slackInvitedAt`) to the auth/member response. Surfaced by wave-slack §7.2 e2e (skipped pending this fix). Flagged 2026-04-30.
- [ ] **Admin members list row mutation isn't reactive.** `markSlackInvited` in `app/pages/admin/members/index.vue` does `Object.assign(member, res.member)` on a plain object inside a `useFetch` array; Vue doesn't react, so the "Mark as Slack invited" button stays visible until a manual reload. Fix: `members.value[i] = { ...members.value[i], ...res.member }` or `splice`. Detail page uses the right pattern (covered by §6.6). Surfaced by wave-slack §6.2 e2e (skipped pending this fix). Flagged 2026-04-30.
- [ ] **Deprecated `slackInviteStatus` field still serialized.** Removed from UI but still on `Member` documents and the `/api/admin/members` payload. Project it away in the API response and run a one-shot `$unset` cleanup. Surfaced by wave-slack §6.7 e2e. Flagged 2026-04-30.
- [ ] **Spec vs shipped-UI mismatch on wave language.** `docs/specs/wave-based-slack-onboarding-tests.md` §7.5 asserts "no wave/cohort/batch language" in the dashboard note, but the shipped welcome-email and dashboard copy say "monthly onboarding waves." Decide which side wins; update the other.
- [ ] **E2E coverage for `e2e/wave-slack-onboarding.spec.js`.** 9 of 16 scaffolded tests now passing (admin Slack-invited button + non-trivial dashboard cases). 7 remain skipped pending the bugs above (7.2, 6.2), seeding gaps (7.4 — no dev endpoint to mint members of arbitrary status), Open Questions (7.8, 6.9), or spec-vs-UI conflicts (7.5, 6.7).
- [ ] **Pilot exit decision (~8 weeks post-launch).** Either restore `server/_archive/utils/checkSlackJoins.js` + its plugin if polling is needed, or delete the archive permanently. Driven by whether the manual-invite cadence is sustainable post-pilot. - [ ] **Pilot exit decision (~8 weeks post-launch).** Either restore `server/_archive/utils/checkSlackJoins.js` + its plugin if polling is needed, or delete the archive permanently. Driven by whether the manual-invite cadence is sustainable post-pilot.
- [ ] **`slack_invite_failed` enum slug cleanup.** Detector and alert removed in `d15458b`, but the slug remains in `server/models/adminAlertDismissal.js` enum so historical dismissal rows continue to validate. Full removal needs a one-shot cleanup of stale dismissal rows in the DB. Roll into a future schema-tidy pass. - [ ] **`slack_invite_failed` enum slug cleanup.** Detector and alert removed in `d15458b`, but the slug remains in `server/models/adminAlertDismissal.js` enum so historical dismissal rows continue to validate. Full removal needs a one-shot cleanup of stale dismissal rows in the DB. Roll into a future schema-tidy pass.
@ -79,6 +86,8 @@ Items surfaced during the 2026-04-29 /simplify review. The 2026-04-30 small-wins
- [ ] **Extract `.tint-candle` / `.tint-ember` utility classes.** The `color-mix(in srgb, var(--candle) 15%, transparent)` + matching border pattern is now inlined as `style=""` in ~9 sites across `EventSeriesTicketCard.vue`, `SeriesPassPurchase.vue`, `NaturalDateInput.vue`, `ImageUpload.vue`. Promote to utility classes in `app/assets/css/main.css` so future tints don't keep multiplying inline styles (and so `:hover` / `:focus` variants are reachable). - [ ] **Extract `.tint-candle` / `.tint-ember` utility classes.** The `color-mix(in srgb, var(--candle) 15%, transparent)` + matching border pattern is now inlined as `style=""` in ~9 sites across `EventSeriesTicketCard.vue`, `SeriesPassPurchase.vue`, `NaturalDateInput.vue`, `ImageUpload.vue`. Promote to utility classes in `app/assets/css/main.css` so future tints don't keep multiplying inline styles (and so `:hover` / `:focus` variants are reachable).
- [ ] **Audit `member &&` truthy checks in sibling ticket/subscription routes.** Commit `f66455e` fixed `server/api/events/[id]/tickets/available.get.js:115` to use `hasMemberAccess(member)`. Same anti-pattern likely exists in adjacent routes (`tickets/purchase.post.js`, subscription endpoints). Guests/suspended/cancelled members would currently look like full members for any feature gated on truthiness alone. - [ ] **Audit `member &&` truthy checks in sibling ticket/subscription routes.** Commit `f66455e` fixed `server/api/events/[id]/tickets/available.get.js:115` to use `hasMemberAccess(member)`. Same anti-pattern likely exists in adjacent routes (`tickets/purchase.post.js`, subscription endpoints). Guests/suspended/cancelled members would currently look like full members for any feature gated on truthiness alone.
- [ ] **STATUS_LABELS dedup — verify.** The 2026-04-30 small-wins batch claimed STATUS_LABELS dedup, but `e2e/admin-members.spec.js` expansion found an inline copy still at `app/pages/admin/members/index.vue:491` and another at `app/pages/member/account.vue:420`. Either the previous dedup was partial or a new copy was reintroduced — confirm and finish dedup into a shared constants module.
- [ ] **`app/pages/admin/members/[id].vue` status select still hand-written.** Commit `441a5f5` aligned the index page's status `<select>` to `STATUS_LABELS`, but the detail page (`[id].vue`) still hand-codes raw status options. Refactor to drive from the same constant.
--- ---
@ -88,6 +97,19 @@ Items surfaced during the 2026-04-29 /simplify review. The 2026-04-30 small-wins
--- ---
## E2e infrastructure gaps
Surfaced during the 2026-04-30 e2e expansion. None block a green suite, but each blocks specific coverage from being added.
- [ ] **Other email routes still send real emails in dev mode.** The `ALLOW_DEV_TEST_ENDPOINTS` short-circuit was added to `server/api/admin/pre-registrants/invite.post.js` (which calls `new Resend(...)` directly), but the five wrapper functions in `server/utils/resend.js` (event registration, cancellation, waitlist, series pass, welcome) still dispatch live. Either add the same gate to each wrapper, or refactor the wrappers into a single `sendEmail({ from, to, subject, text, html })` helper holding the gate centrally — would also dedupe ~5 near-identical try/catch blocks.
- [ ] **No dev endpoint to seed members of arbitrary status.** Wave-slack §7.4 (note hidden for suspended/cancelled/guest) is gated on this. `/api/dev/test-login` only mints an `active` admin. A minimal `/api/dev/members.post` accepting `{ email, status, slackInvited, ... }` would unblock many more dashboard-state e2e tests.
- [ ] **SSR `useFetch` blocks `page.route` mocking.** Page-level fetches in `[slug].vue` files run during SSR and can't be intercepted client-side. Affects: hidden-event 404 e2e, any test that needs a mocked event payload before client hydration. Either expose a client-side fetch alternative, add a server-side test mock layer, or accept that DB seeding is required for these cases.
- [ ] **Self-cancel block on paid event registrations not e2e-tested.** Requires seeding a logged-in member with a paid registration row. Out of scope for this round.
- [ ] **Visual snapshot for `join — desktop` is stale.** 12,676px diff (2% of image) from layout drift. Regenerate via `npx playwright test --update-snapshots e2e/visual/pages.spec.js` once a designer eyeballs the diff.
- [ ] **E2e cross-file races on admin specs.** With `fullyParallel: false` + `workers: 4` + `retries: 1`, ~1 admin CRUD test still fails per full-suite run (rotates between `admin-events` CRUD, `board` page-loads, and wave-slack §6.4). Each passes 100% in isolation. Root cause: tests anchor on "first row" / "any visible button" rather than uniquely-identified data, so they race when other admin specs mutate the shared dev DB. Proper fix is per-test data isolation: each test creates its own scoped record with a `Date.now()` suffix and queries by that exact identifier. Out of scope for the e2e expansion.
---
## Deeplink memories ## Deeplink memories
- `project_post_launch_backlog.md` — high-level digest of this file - `project_post_launch_backlog.md` — high-level digest of this file