TC-EVT-009: Waitlist
🆕 New on stage — #301–#308, #333–#335 (Jun 19 release). Corrects the old "there is no waitlist" guidance on TC-EVT-005 and the Test Plan — that is now FALSE. Waitlist is ON by default for every event that reaches capacity; there is no per-event toggle, only the global backend env var
WAITLIST_ENABLED='false'.
Module: Events & Registrations — Waitlist
Primary Test Users: testmember@rcme.membervu.com / Member123!, guest@demo.membervu.com / Guest123!, an anonymous browser session, and events@demo.membervu.com / Events123! (admin queue actions).
Priority: P1
Objectives
- Fill a free event to capacity, then confirm a member, a member+guest, and an anonymous public registration each land on the waitlist instead of being rejected.
- Admin waitlist queue shows entries in FIFO join order.
- Approve a waitlisted entry — including with a capacity override when the event is still full.
- Decline a waitlisted entry removes it from the queue.
- Approving an entry that is not
WAITLISTED(e.g. alreadyCHECKED_IN) is a safe no-op, NOT an error. - A brand-new approved guest receives a claim-link email whose host is the correct tenant origin.
- A waitlisted guest does not get the join-time account-setup email — only on approval.
- The public event page shows a "Join Waitlist" CTA on a full free event (not on a full paid event).
Scenario summary
| ID | Scenario | Key data assertion |
|---|---|---|
| WL9-01 | Member registers on a full event | Registration created with status WAITLISTED (Prisma EventRegistrationStatus), not rejected with a capacity error. |
| WL9-02 | Member + guest registers on a full event | Both the member's and the guest's registration rows are WAITLISTED. |
| WL9-03 | Anonymous public registers on a full event | Public registration (POST /api/public/:tenantSlug/events/:slug/register) also lands WAITLISTED, same as the authenticated path. |
| WL9-04 | Admin waitlist queue order | GET /admin/events/:eventId/waitlist returns entries ordered by createdAt asc (FIFO) — first-to-join is first in the list. |
| WL9-05 | Approve with capacity override | Event still at capacity, override:true → 200, registration flips WAITLISTED→CONFIRMED, confirmed count now exceeds nominal capacity by design (logged as an audit warning, INV-4). |
| WL9-06 | Approve without override, event full | 409 {"code":"WAITLIST_NO_SEATS"} — the ONLY 409 case on approve. |
| WL9-07 | Decline | WAITLISTED→CANCELLED; entry disappears from the queue; re-declining the same (now CANCELLED) row is a 200 no-op, not an error. |
| WL9-08 | Approving a CHECKED_IN / non-WAITLISTED row | 200 {"alreadyApproved":true} — idempotent no-op, NOT a 409, NOT a duplicate email. (Corrects an earlier assumption that this case 409s.) |
| WL9-09 | Approved-guest claim link | Approval email to a brand-new guest contains a claim link whose host matches the tenant origin (not a broken/wrong domain); link resolves and lets the guest set up / confirm. |
| WL9-10 | No setup email at waitlist join time | A guest placed on the waitlist gets NO account-setup email when joining — only when later approved. |
| WL9-11 | Public "Join Waitlist" CTA — free only | A full free event's public page shows "Join Waitlist"; a full paid event does NOT (the CTA is gated on isFreeEvent in the frontend, even though the backend accepts waitlist registrations for both). |
➡️ Full click-by-click steps: TC-EVT-009 (Detailed).