/* Repeatable landing-page screenshots (re-run after UI changes). * * Usage (frontend container, dev server running): * npm run screenshots # light scheme (default) * npm run screenshots -- --scheme=dark * * Captures real app states into public/screenshots/ (committed, so the * landing page always shows current UI). Authenticated states are out of * scope (magic-link login is not scriptable without SMTP). */ import { mkdirSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { chromium } from "playwright"; const root = join(dirname(fileURLToPath(import.meta.url)), ".."); const outDir = join(root, "public", "screenshots"); const base = process.env.SCREENSHOT_BASE_URL ?? "http://localhost:3000"; const schemeArg = process.argv.find((a) => a.startsWith("--scheme=")); const scheme = schemeArg ? schemeArg.split("=")[1] : "light"; const shots = [ { name: "hero", path: "/", fullPage: true }, { name: "workflows", path: "/app/workflows", fullPage: false, selectFlow: "intake_form", }, ]; const browser = await chromium.launch(); try { mkdirSync(outDir, { recursive: true }); const context = await browser.newContext({ viewport: { width: 1440, height: 900 }, colorScheme: scheme === "dark" ? "dark" : "light", }); await context.addInitScript( (value) => { try { localStorage.setItem("kirche-color-scheme", value); } catch { /* private mode */ } }, scheme === "dark" ? "dark" : "light", ); const page = await context.newPage(); for (const shot of shots) { await page.goto(base + shot.path, { waitUntil: "networkidle" }); await page.waitForTimeout(1500); if (shot.selectFlow) { // Show the generated RJSF form instead of the default first flow. await page.locator('[role="combobox"]').first().click(); await page.getByRole("option", { name: shot.selectFlow }).click(); await page.waitForTimeout(2000); } const file = join(outDir, `${shot.name}-${scheme}.png`); await page.screenshot({ path: file, fullPage: shot.fullPage }); console.log(`wrote ${file}`); } } finally { await browser.close(); }