Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 2m34s
CI / Backend Unit Tests (pull_request) Failing after 2m49s
CI / E2E Tests (pull_request) Failing after 1h24m49s
- captureProofshots() now accepts an optional setup(page) callback that runs before each screenshot's page.goto(), so localStorage can be injected reliably without loading a backend-dependent page - dashboard-screenshots.spec.ts seeds 2 notifications (MENTION + REPLY) for admin via direct DB insert in beforeAll, cleans up in afterAll - localStorage.familienarchiv.lastVisited injected directly via page.evaluate() — no fragile document page navigation needed - Updated screenshots committed (all 6 now show all 4 widgets) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
/**
|
||
* Shared proofshot helper for Playwright.
|
||
*
|
||
* Basic usage:
|
||
* import { captureProofshots } from './proofshots';
|
||
* captureProofshots('/persons', 'persons');
|
||
*
|
||
* With per-test setup (e.g. seed localStorage before navigation):
|
||
* captureProofshots('/persons', 'persons', {
|
||
* setup: async (page) => {
|
||
* await page.goto('/persons/some-id'); // populates any localStorage state
|
||
* }
|
||
* });
|
||
*
|
||
* The setup callback runs before each screenshot's page.goto(url), so any
|
||
* localStorage values it writes persist into the main navigation.
|
||
*
|
||
* Screenshots are saved to proofshot-artifacts/{featureName}/.
|
||
*/
|
||
import { type Page, test } from '@playwright/test';
|
||
import path from 'path';
|
||
import fs from 'fs';
|
||
import { fileURLToPath } from 'url';
|
||
|
||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||
|
||
const viewports = [
|
||
{ name: 'mobile', width: 390, height: 844 },
|
||
{ name: 'tablet', width: 768, height: 1024 },
|
||
{ name: 'desktop', width: 1440, height: 900 }
|
||
];
|
||
|
||
interface ProofshotOptions {
|
||
/**
|
||
* Optional async callback that runs before each screenshot's page.goto(url).
|
||
* Use it to seed localStorage, visit a prerequisite page, etc.
|
||
*/
|
||
setup?: (page: Page) => Promise<void>;
|
||
}
|
||
|
||
/**
|
||
* Registers Playwright tests that navigate to `url`, apply each theme,
|
||
* and capture full-page screenshots at all standard viewports.
|
||
*
|
||
* @param url The path to screenshot (e.g. '/', '/persons', '/admin')
|
||
* @param featureName Used as the output directory name and screenshot file prefix
|
||
* @param options Optional setup callback and other options
|
||
*/
|
||
export function captureProofshots(
|
||
url: string,
|
||
featureName: string,
|
||
options?: ProofshotOptions
|
||
): void {
|
||
const outDir = path.join(__dirname, '../../proofshot-artifacts', featureName);
|
||
fs.mkdirSync(outDir, { recursive: true });
|
||
|
||
for (const vp of viewports) {
|
||
for (const theme of ['light', 'dark'] as const) {
|
||
test(`${featureName} – ${vp.name} – ${theme}`, async ({ page }) => {
|
||
// Run optional setup before main navigation (e.g. seed localStorage)
|
||
if (options?.setup) {
|
||
await options.setup(page);
|
||
}
|
||
|
||
await page.setViewportSize({ width: vp.width, height: vp.height });
|
||
await page.goto(url);
|
||
|
||
// Apply theme via data-theme attribute and localStorage
|
||
await page.evaluate((t) => {
|
||
document.documentElement.setAttribute('data-theme', t);
|
||
localStorage.setItem('theme', t);
|
||
}, theme);
|
||
|
||
// 'networkidle' is unreliable in SvelteKit dev mode due to the HMR WebSocket.
|
||
await page.waitForLoadState('domcontentloaded');
|
||
await page.waitForSelector('main', { state: 'visible' });
|
||
|
||
await page.screenshot({
|
||
path: path.join(outDir, `${featureName}-${vp.name}-${theme}.png`),
|
||
fullPage: true
|
||
});
|
||
});
|
||
}
|
||
}
|
||
}
|