- Waitlist per session: entries for pick-sessions tickets name a session; offers use that session's free places, never run past its start, and claim links tick it. Held offers count towards session capacity. - At the door: the Select items pop-up has the session picker, with today's session preselected for new attendees. - On pick-sessions events every ticket shows the session list straight away. "All sessions" tickets record the ticked sessions (RegistrationOption.sessionIds) at one price; scanning, attendance, certificates, reminders and capacity follow them. - Fix: per-session stock limits weren't enforced (takenCount filtered WaitlistEntry by a sessionId column that didn't exist, and the error was swallowed), and the public event page lost its stock info. - Fix: editing a door registration with picked sessions couldn't be saved. - Fix: the offline-scanning service worker served /_next/static cache-first forever, so dev browsers that had opened the scanner ran stale code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
95 lines
5.0 KiB
TypeScript
95 lines
5.0 KiB
TypeScript
import { test, expect, seed, loginAs, api } from "./fixtures";
|
|
|
|
type Registration = { id: string; eventId: string; user?: { name: string }; registrationOptions: { sessionId?: string | null; sessionIds?: string[]; priceSnapshot: number; quantity: number }[] };
|
|
type WaitlistEntry = { eventId: string; sessionId: string | null; quantity: number };
|
|
|
|
test.describe("pick sessions", () => {
|
|
test("book two classes of a drop-in event; a full class can't be ticked", async ({ page }) => {
|
|
await loginAs(page, "user");
|
|
await page.goto(`/register/${seed().events.dropIn}`);
|
|
await expect(page.getByText("R50.00 per session").first()).toBeVisible();
|
|
await page.getByRole("button", { name: "+" }).first().click();
|
|
|
|
const picker = page.getByRole("group", { name: "Choose sessions" });
|
|
await expect(picker.getByText("Full")).toBeVisible();
|
|
await expect(picker.getByRole("checkbox").first()).toBeDisabled();
|
|
await picker.getByRole("checkbox").nth(1).check();
|
|
await picker.getByRole("checkbox").nth(2).check();
|
|
await expect(page.getByText("Total: R100.00")).toBeVisible();
|
|
|
|
await page.getByRole("button", { name: "Register", exact: true }).click();
|
|
await page.waitForURL(/\/registration\/success/);
|
|
|
|
const regs = await api<Registration[]>(page, "user", "GET", "/api/registrations/myregistrations");
|
|
const reg = regs.find((r) => r.eventId === seed().events.dropIn);
|
|
expect(reg?.registrationOptions.filter((o) => o.sessionId)).toHaveLength(2);
|
|
});
|
|
|
|
test("an all-sessions pass: tick the days, pay one price", async ({ page }) => {
|
|
await loginAs(page, "user");
|
|
await page.goto(`/register/${seed().events.conference}`);
|
|
await expect(page.getByText("R200.00", { exact: true })).toBeVisible();
|
|
await expect(page.getByText("per session")).toHaveCount(0);
|
|
|
|
const picker = page.getByRole("group", { name: "Choose sessions" });
|
|
await picker.getByRole("checkbox").nth(0).check();
|
|
await picker.getByRole("checkbox").nth(2).check();
|
|
await expect(page.getByText("Total: R200.00")).toBeVisible();
|
|
|
|
await page.getByRole("button", { name: "Register", exact: true }).click();
|
|
await page.waitForURL(/\/registration\/success/);
|
|
|
|
const regs = await api<Registration[]>(page, "user", "GET", "/api/registrations/myregistrations");
|
|
const line = regs.find((r) => r.eventId === seed().events.conference)?.registrationOptions[0];
|
|
expect(line?.sessionId ?? null).toBeNull();
|
|
expect(line?.sessionIds).toHaveLength(2);
|
|
expect(line?.priceSnapshot).toBe(200);
|
|
expect(line?.quantity).toBe(1);
|
|
});
|
|
|
|
test("join the waitlist for a full class", async ({ page }) => {
|
|
await loginAs(page, "admin");
|
|
await page.goto(`/register/${seed().events.dropIn}`);
|
|
await page.getByRole("button", { name: "+" }).first().click();
|
|
|
|
const picker = page.getByRole("group", { name: "Choose sessions" });
|
|
await picker.getByRole("button", { name: "Join waitlist" }).click();
|
|
await expect(page.getByText(/Drop-in — Class 1/)).toBeVisible();
|
|
await page.locator("form").filter({ hasText: "Join the waitlist" }).getByRole("button", { name: "Join waitlist" }).click();
|
|
await expect(page.getByText(/You're on the waitlist/)).toBeVisible();
|
|
|
|
const mine = await api<WaitlistEntry[]>(page, "admin", "GET", "/api/waitlist/mine");
|
|
const entry = mine.find((e) => e.eventId === seed().events.dropIn);
|
|
expect(entry?.sessionId).toBeTruthy();
|
|
expect(entry?.quantity).toBe(1);
|
|
});
|
|
|
|
test("at the door: book a class for a walk-in", async ({ page }) => {
|
|
await loginAs(page, "supervisor");
|
|
await page.goto("/dashboard/supervisor/at-the-door");
|
|
const value = await page.locator("option", { hasText: "E2E Drop-in Class" }).getAttribute("value");
|
|
// The page picks a default event once its list loads; choose ours after that.
|
|
await page.waitForLoadState("networkidle");
|
|
await page.locator("select").first().selectOption(value!);
|
|
await page.waitForLoadState("networkidle");
|
|
await expect(page.locator("select").first()).toHaveValue(value!);
|
|
|
|
await page.getByPlaceholder("Name, email or phone…").fill("Door Walk In");
|
|
await page.getByText('New attendee "Door Walk In"…').click();
|
|
await page.getByPlaceholder("Email address").fill("door-walkin@e2e.test");
|
|
await page.getByRole("button", { name: "Next — Choose Items" }).click();
|
|
|
|
await expect(page.getByText("R 50.00 per session")).toBeVisible();
|
|
await page.getByRole("button", { name: "+" }).first().click();
|
|
const picker = page.getByRole("group", { name: "Choose sessions" });
|
|
await picker.getByRole("checkbox").nth(1).check();
|
|
await expect(page.getByText("Total: R 50.00")).toBeVisible();
|
|
await page.getByRole("button", { name: "Confirm Registration" }).click();
|
|
await expect(page.getByText("Select Items")).toBeHidden();
|
|
|
|
const regs = await api<Registration[]>(page, "supervisor", "GET", `/api/registrations/event/${seed().events.dropIn}`);
|
|
const reg = regs.find((r) => r.user?.name === "Door Walk In");
|
|
expect(reg?.registrationOptions.filter((o) => o.sessionId)).toHaveLength(1);
|
|
});
|
|
});
|