Milestone A of the frontend test plan. Sets up the test rig — config, globalSetup that probes the backend and seeds an admin session into storageState, lightweight fixtures, and a 3-test smoke spec — without yet covering any user journeys (those land in Milestone B). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
import { request, type APIRequestContext } from '@playwright/test';
|
|
import { promises as fs } from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
const API_BASE = process.env.E2E_API_BASE ?? 'http://127.0.0.1:18080';
|
|
const STATE_PATH = path.join(__dirname, '..', '.auth', 'admin.json');
|
|
|
|
interface StoredState {
|
|
origins: Array<{
|
|
origin: string;
|
|
localStorage: Array<{ name: string; value: string }>;
|
|
}>;
|
|
}
|
|
|
|
let cachedToken: string | null = null;
|
|
|
|
async function readAdminToken(): Promise<string> {
|
|
if (cachedToken) return cachedToken;
|
|
const raw = await fs.readFile(STATE_PATH, 'utf8');
|
|
const state = JSON.parse(raw) as StoredState;
|
|
for (const origin of state.origins) {
|
|
const entry = origin.localStorage.find((e) => e.name === 'picloud.admin.token');
|
|
if (entry) {
|
|
cachedToken = entry.value;
|
|
return entry.value;
|
|
}
|
|
}
|
|
throw new Error(`No picloud.admin.token in ${STATE_PATH} — did globalSetup run?`);
|
|
}
|
|
|
|
// Thin wrapper around Playwright's request context that injects the
|
|
// admin bearer token from the shared storageState. Use this for
|
|
// setup/teardown shortcuts when the *test itself* is about something
|
|
// else (e.g., a script-editor test that just needs an app to exist).
|
|
export async function adminApi(): Promise<APIRequestContext> {
|
|
const token = await readAdminToken();
|
|
return request.newContext({
|
|
baseURL: API_BASE,
|
|
extraHTTPHeaders: {
|
|
authorization: `Bearer ${token}`,
|
|
'content-type': 'application/json'
|
|
}
|
|
});
|
|
}
|