const fs = require('fs'); const path = require('path'); const { chromium } = require('playwright'); const BASE_URL = process.env.BASE_URL || 'http://127.0.0.1:8000/'; const ARTIFACTS = path.resolve(process.env.ARTIFACTS_DIR || path.join(__dirname, 'artifacts')); fs.mkdirSync(ARTIFACTS, { recursive: true }); function assert(condition, message) { if (!condition) throw new Error(message); } function trackErrors(page) { const errors = []; page.on('console', (message) => { if (message.type() === 'error') errors.push(`console: ${message.text()}`); }); page.on('pageerror', (error) => errors.push(`pageerror: ${error.message}`)); page.on('response', (response) => { if (response.status() >= 400) errors.push(`http ${response.status()}: ${response.url()}`); }); return errors; } async function launch(viewport = { width: 1440, height: 1000 }) { const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport, deviceScaleFactor: 1 }); return { browser, page }; } async function open(page) { await page.goto(BASE_URL, { waitUntil: 'networkidle' }); await page.waitForTimeout(800); } async function screenshot(page, name) { await page.screenshot({ path: path.join(ARTIFACTS, name), fullPage: true }); } async function run(name, fn) { const started = Date.now(); try { await fn(); console.log(`PASS ${name} (${Date.now() - started}ms)`); } catch (error) { console.error(`FAIL ${name}: ${error.stack || error.message}`); process.exitCode = 1; } } module.exports = { BASE_URL, ARTIFACTS, assert, trackErrors, launch, open, screenshot, run, };