import { test as base, expect, type Page } from "@playwright/test"; import fs from "fs"; import path from "path"; export type Role = "admin" | "supervisor" | "staff" | "user"; export type Seed = { users: Record; events: { free: string; paid: string; course: string; dropIn: string; conference: string }; course: { sessions: { id: string; label: string }[]; ticketId: string; qrCode: string }; unsubscribeToken: string; newsPromptUser: { id: string; token: string }; retention: { toWarn: string; toAnonymise: string }; }; export const API = "http://localhost:5100"; // Written by e2e/support/prepare-db.js when the e2e backend starts, so read lazily. let cached: Seed | null = null; export function seed(): Seed { if (!cached) cached = JSON.parse(fs.readFileSync(path.join(__dirname, ".data", "seed.json"), "utf8")) as Seed; return cached; } /** Signs the page in as a seeded user (the token goes where the app keeps it). */ export async function loginAs(page: Page, role: Role) { await page.addInitScript((token) => { localStorage.setItem("hope_events_token", token); }, seed().users[role].token); } export const test = base.extend({ page: async ({ page }, use) => { // Skip the cookie notice so it never covers what the tests click. await page.addInitScript(() => localStorage.setItem("hope_events_cookie_consent", "declined")); await use(page); }, }); /** Calls the e2e API as a seeded user. */ export async function api(page: Page, role: Role, method: string, url: string, body?: unknown): Promise { const res = await page.request.fetch(`${API}${url}`, { method, headers: { Authorization: `Bearer ${seed().users[role].token}`, "Content-Type": "application/json" }, data: body === undefined ? undefined : JSON.stringify(body), }); const text = await res.text(); if (!res.ok()) throw new Error(`${method} ${url} → ${res.status()}: ${text}`); return (text ? JSON.parse(text) : null) as T; } export { expect };