#!/usr/bin/env node /** * Screenshot Capture Script for Visual Regression Testing * * Captures screenshots of web pages at multiple viewports using Playwright. * Used to create baseline or current screenshots. * * Usage: node capture-screenshots.js [baseline|current] * baseline - Save to tests/visual/baseline/ * current - Save to tests/visual/current/ */ const { chromium } = require('playwright'); const fs = require('fs'); const path = require('path'); const { BASE_ARGS } = require('./lib/browser-launcher'); const TARGET_URL = process.env.TARGET_URL || 'http://host.docker.internal:3000'; const MODE = process.argv[2] || 'current'; const VIEWPORTS = [ { name: 'mobile', width: 375, height: 667 }, { name: 'tablet', width: 768, height: 1024 }, { name: 'desktop', width: 1280, height: 720 }, ]; const PAGES = [ { name: 'homepage', path: '/' }, { name: 'admin-login', path: '/admin/login' }, ]; const SCREENSHOT_BASE = path.join(__dirname, '..', 'visual'); async function captureScreenshots() { const outputDir = path.join(SCREENSHOT_BASE, MODE); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } console.log(`=== Screenshot Capture: ${MODE} ===\n`); console.log(`Target URL: ${TARGET_URL}`); console.log(`Output: ${outputDir}\n`); const browser = await chromium.launch({ headless: true, args: [...BASE_ARGS, '--disable-setuid-sandbox'], }); let totalCaptured = 0; let totalFailed = 0; for (const page_config of PAGES) { for (const viewport of VIEWPORTS) { const filename = `${page_config.name}_${viewport.name}.png`; const filePath = path.join(outputDir, filename); const context = await browser.newContext({ viewport: { width: viewport.width, height: viewport.height }, deviceScaleFactor: 1, }); const page = await context.newPage(); try { const url = `${TARGET_URL}${page_config.path}`; console.log(` Capturing: ${url} [${viewport.name}]`); await page.goto(url, { waitUntil: 'commit', timeout: 30000 }); await page.waitForLoadState('domcontentloaded', { timeout: 15000 }).catch(() => {}); await page.waitForTimeout(1000); await page.screenshot({ path: filePath, fullPage: true, }); const fileSize = fs.statSync(filePath).size; console.log(` āœ… Saved: ${filename} (${(fileSize / 1024).toFixed(1)} KB)`); totalCaptured++; } catch (error) { console.log(` āŒ Failed: ${filename} - ${error.message}`); totalFailed++; } finally { await context.close(); } } } await browser.close(); console.log(`\nšŸ“Š Summary:`); console.log(` Mode: ${MODE}`); console.log(` āœ… Captured: ${totalCaptured}`); console.log(` āŒ Failed: ${totalFailed}`); console.log(` šŸ“ Output: ${outputDir}`); process.exit(totalFailed > 0 ? 1 : 0); } captureScreenshots().catch((err) => { console.error('Fatal error:', err); process.exit(1); });