import { type APIRequestContext, type APIResponse, expect, } from "@playwright/test"; export async function expectPageRedirectsToLogin( request: APIRequestContext, path: string, ): Promise { const response = await request.get(path, { maxRedirects: 0 }); expectRedirectToLogin(response, path); } export async function expectApiAuthRequired( request: APIRequestContext, path: string, options?: { method?: "GET" | "POST"; data?: unknown }, ): Promise { const method = options?.method ?? "GET"; const response = await request.fetch(path, { method, data: options?.data, maxRedirects: 0, }); expect(response.status()).toBe(401); const body = await response.json(); expect(body).toMatchObject({ error: "Authentication required", redirectTo: "/auth/login", }); } export function expectRedirectToLogin( response: APIResponse, returnPath: string, ): void { expect(response.status()).toBe(302); const location = response.headers()["location"]; expect(location).toBeTruthy(); const loginUrl = new URL(location!, "http://localhost:8080"); expect(loginUrl.pathname).toBe("/auth/login"); expect(loginUrl.searchParams.get("return_path")).toBe(returnPath); } export function getSetCookies(response: APIResponse): string[] { return response.headersArray() .filter((header) => header.name.toLowerCase() === "set-cookie") .map((header) => header.value); } export function readCookieFromSetCookieHeader( setCookies: string[], cookieName: string, ): string | null { const pattern = new RegExp(`^${cookieName}=([^;]*)`); for (const setCookie of setCookies) { const match = pattern.exec(setCookie); if (match) { return match[1]; } } return null; }