Files
PiCloud/dashboard/tests/e2e/fixtures/ids.ts
MechaCat02 74f7b3b631 test(dashboard): add Playwright e2e scaffolding with smoke spec
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>
2026-05-28 07:03:44 +02:00

43 lines
1.5 KiB
TypeScript

/* eslint-disable no-empty-pattern -- Playwright fixtures require an
object-pattern first arg; these fixtures don't depend on any other
fixture so the pattern is intentionally empty. */
import { test as base } from '@playwright/test';
import { randomBytes } from 'node:crypto';
// Tests share a single backend/Postgres. To avoid collisions we tag
// every resource the test creates with a short random suffix plus the
// Playwright worker index. This way two workers running the same spec
// in parallel never fight over the same slug or username.
export function shortId(): string {
return randomBytes(3).toString('hex');
}
export function uniqueSlug(prefix: string, workerIndex: number): string {
const cleaned = prefix
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');
return `e2e-${cleaned}-w${workerIndex}-${shortId()}`;
}
export function uniqueUsername(prefix: string, workerIndex: number): string {
// Username regex is [a-z0-9._-]{2,32}. Mirror the slug format.
const cleaned = prefix.toLowerCase().replace(/[^a-z0-9]+/g, '');
return `e2e${cleaned}w${workerIndex}${shortId()}`.slice(0, 32);
}
export const test = base.extend<{
uniqueSlug: (prefix: string) => string;
uniqueUsername: (prefix: string) => string;
}>({
uniqueSlug: async ({}, use, testInfo) => {
await use((prefix) => uniqueSlug(prefix, testInfo.workerIndex));
},
uniqueUsername: async ({}, use, testInfo) => {
await use((prefix) => uniqueUsername(prefix, testInfo.workerIndex));
}
});
export { expect } from '@playwright/test';