import { chromium, Browser, Page } from '@playwright/test'; import * as fs from 'fs/promises'; export interface FormAction { type: 'fill' | 'click' | 'check'; selector: string; value?: string; } export interface ScreenshotConfig { url: string; name: string; waitFor?: string; // CSS selector to wait for delay?: number; // ms to wait after page load actions?: FormAction[]; // Actions to perform before screenshot } export interface CaptureOptions { baseUrl: string; outputDir: string; viewport?: { width: number; height: number }; } const DEFAULT_OPTIONS: CaptureOptions = { baseUrl: 'http://localhost:18188', outputDir: 'screenshots', viewport: { width: 1920, height: 1080 }, }; export async function captureScreenshots( screenshots: ScreenshotConfig[], options: Partial = {} ): Promise { const opts = { ...DEFAULT_OPTIONS, ...options }; const browser = await chromium.launch(); const page = await browser.newPage(); await page.setViewportSize(opts.viewport!); const captured: string[] = []; for (const config of screenshots) { const url = config.url.startsWith('http') ? config.url : `${opts.baseUrl}${config.url}`; await page.goto(url, { waitUntil: 'networkidle' }); // Execute any form actions before screenshot if (config.actions) { for (const action of config.actions) { if (action.type === 'fill' && action.value) { await page.fill(action.selector, action.value); } else if (action.type === 'click') { await page.click(action.selector); } else if (action.type === 'check') { await page.check(action.selector); } } } if (config.waitFor) { await page.waitForSelector(config.waitFor, { timeout: 10000 }); } if (config.delay) { await page.waitForTimeout(config.delay); } const path = `${opts.outputDir}/${config.name}`; await page.screenshot({ path, type: 'png' }); console.log(`✓ ${config.name}`); captured.push(path); } await browser.close(); return captured; } export async function captureSingle( url: string, name: string, options: Partial = {} ): Promise { const [path] = await captureScreenshots([{ url, name }], options); return path; } export { Browser, Page }; // CLI runner async function main() { const configPath = process.argv[2]; if (!configPath) { console.error('Usage: pnpm capture '); console.error(''); console.error('Config format:'); console.error(JSON.stringify({ baseUrl: 'http://localhost:18188', outputDir: 'screenshots', screenshots: [ { url: '/page', name: 'screenshot.png' }, { url: '/other', name: 'other.png', waitFor: '.selector', delay: 500 }, ], }, null, 2)); process.exit(1); } const config = JSON.parse(await fs.readFile(configPath, 'utf-8')); // Ensure output directory exists await fs.mkdir(config.outputDir || 'screenshots', { recursive: true }); await captureScreenshots(config.screenshots, { baseUrl: config.baseUrl, outputDir: config.outputDir, }); console.log(`\nDone! ${config.screenshots.length} screenshots saved to ${config.outputDir || 'screenshots'}/`); } main();