Files
pargar/frontend/e2e/helpers.ts
T

84 lines
3.0 KiB
TypeScript
Raw Permalink Normal View History

import { type Page, test } from "@playwright/test";
import * as fs from "fs";
import * as path from "path";
export const ADMIN_EMAIL = "admin";
export const ADMIN_PASSWORD = "wZW64CUbXbv9679dmR1FIbz3";
export const BASE = "https://localhost";
const AUTH_FILE = path.join(__dirname, ".auth-state.json");
interface AuthState {
available: boolean;
accessToken?: string;
refreshToken?: string;
user?: { id: number; role: string; email: string };
}
export function loadAuth(): AuthState {
try {
return JSON.parse(fs.readFileSync(AUTH_FILE, "utf-8")) as AuthState;
} catch {
return { available: false };
}
}
/** Skip this test if auth is not available (CAPTCHA not exposed). */
export function requireAuth(): AuthState {
const auth = loadAuth();
if (!auth.available) {
test.skip(true, "Auth not available — restart API with CAPTCHA_EXPOSE_ANSWER=true");
}
return auth;
}
/** Inject cached auth cookies into the page context. */
export async function injectAuth(page: Page): Promise<AuthState> {
const auth = requireAuth();
// Seed Zustand persist store so the app hydrates with a valid user (skips redirect)
await page.addInitScript(({ user }) => {
try {
localStorage.setItem(
"pargar.auth",
JSON.stringify({ state: { user }, version: 0 }),
);
} catch {}
}, { user: auth.user });
await page.context().addCookies([
{ name: "pargar_access", value: auth.accessToken!, domain: "localhost", path: "/", secure: true, sameSite: "Lax" },
{ name: "pargar_refresh", value: auth.refreshToken!, domain: "localhost", path: "/", secure: true, httpOnly: true, sameSite: "Lax" },
]);
return auth;
}
export async function loginAs(page: Page, identity: string, password: string) {
const captchaRes = await page.request.get(`${BASE}/api/auth/captcha`);
const captchaData = await captchaRes.json();
const answer: string = captchaData.answer ?? "";
const challengeId: string = captchaData.challengeId ?? "";
const loginRes = await page.request.post(`${BASE}/api/auth/login`, {
data: { username: identity, password, challengeId, captchaAnswer: answer, rememberMe: false },
});
const loginBody = await loginRes.json();
if (!loginBody.accessToken) {
throw new Error(`Login failed for ${identity}: ${JSON.stringify(loginBody)}`);
}
await page.context().addCookies([
{ name: "access_token", value: loginBody.accessToken, domain: "localhost", path: "/", secure: true, sameSite: "Lax" },
{ name: "refresh_token", value: loginBody.refreshToken, domain: "localhost", path: "/", secure: true, httpOnly: true, sameSite: "Lax" },
]);
return loginBody;
}
export async function apiLogin(page: Page, identity: string, password: string) {
const captchaRes = await page.request.get(`${BASE}/api/auth/captcha`);
const { challengeId, answer } = await captchaRes.json();
const res = await page.request.post(`${BASE}/api/auth/login`, {
data: { username: identity, password, challengeId, captchaAnswer: answer, rememberMe: false },
});
return res.json();
}