Timed jobs move from in-process timers to a job registry run by pg-boss: once per schedule across processes, retries, run history, cron schedules in the church timezone, and an admin Background jobs page with Run now. Playwright end-to-end tests run against their own seeded database. A Gitea Actions workflow runs backend tests, frontend checks and the e2e tests, and deploys v* tags with scripts/deploy.sh once secrets are set. Also fixes the at-the-door check-in count for multi-day tickets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.5 KiB
TypeScript
52 lines
2.5 KiB
TypeScript
import { test, expect, seed, loginAs, api } from "./fixtures";
|
|
|
|
test.describe("multi-day events", () => {
|
|
test("check-in is once per session, and the register and certificates follow", async ({ page }) => {
|
|
const { course, events } = seed();
|
|
|
|
// Scanning today: Week 2.
|
|
const scan = await api<{ session: { label: string } }>(page, "staff", "POST", `/api/tickets/scan/${course.qrCode}`, { qty: 1 });
|
|
expect(scan.session.label).toBe("Week 2");
|
|
await expect(api(page, "staff", "POST", `/api/tickets/scan/${course.qrCode}`, { qty: 1 })).rejects.toThrow(/Already checked in for Week 2/);
|
|
|
|
// The register shows weeks 1 and 2 ticked.
|
|
await loginAs(page, "supervisor");
|
|
await page.goto(`/dashboard/supervisor/attendance?eventId=${events.course}`);
|
|
const row = page.locator("tr", { hasText: "Thandi Test" });
|
|
await expect(row.getByText("2/5")).toBeVisible();
|
|
|
|
// Tick week 3 by hand (e.g. let in without a scan), then untick it.
|
|
const week3 = row.locator("td").nth(3).getByRole("button");
|
|
await week3.click();
|
|
await expect(row.getByText("3/5")).toBeVisible();
|
|
await week3.click();
|
|
await expect(row.getByText("2/5")).toBeVisible();
|
|
|
|
// Two sessions meets the rule (at least 2), so a certificate can be issued now.
|
|
await page.getByRole("button", { name: "Issue now" }).click();
|
|
await expect(page.getByText("1 certificate issued.")).toBeVisible();
|
|
const code = (await row.locator("span.font-mono").innerText()).trim();
|
|
expect(code).toMatch(/^[A-Z0-9]{5}-[A-Z0-9]{5}$/);
|
|
|
|
// Anyone can check it.
|
|
await page.goto(`/certificates/verify/${code}`);
|
|
await expect(page.getByRole("heading", { name: "Valid certificate" })).toBeVisible();
|
|
await expect(page.getByText("Thandi Test")).toBeVisible();
|
|
});
|
|
|
|
test("the attendee sees their certificate on My Events", async ({ page }) => {
|
|
await loginAs(page, "user");
|
|
await page.goto("/dashboard/user");
|
|
await expect(page.getByRole("heading", { name: "My Certificates" })).toBeVisible();
|
|
await expect(page.getByText("E2E Alpha Course").first()).toBeVisible();
|
|
});
|
|
|
|
test("the scanner offers today's session for a multi-day event", async ({ page }) => {
|
|
await loginAs(page, "staff");
|
|
await page.goto("/dashboard/staff/ticket-scanning");
|
|
await page.locator("select").first().selectOption({ label: "E2E Alpha Course" });
|
|
await expect(page.locator("select", { has: page.locator("option", { hasText: "Today's session" }) })).toBeVisible();
|
|
await expect(page.getByText("Today's session (Week 2)")).toBeAttached();
|
|
});
|
|
});
|