const { chromium } = require('playwright'); const fs = require('fs'); const path = require('path'); const TARGET_URL = process.env.TARGET_URL; const PAGES = (process.env.PAGES || '/').split(',').map(p => p.trim()); const REPORTS_DIR = process.env.REPORTS_DIR || './reports'; async function monitorPage(context, pagePath) { const page = await context.newPage(); const fullUrl = `${TARGET_URL}${pagePath}`; const consoleErrors = []; const networkErrors = []; page.on('console', msg => { if (msg.type() === 'error') { consoleErrors.push({ type: 'console_error', text: msg.text(), location: msg.location(), timestamp: new Date().toISOString(), }); } }); page.on('pageerror', err => { consoleErrors.push({ type: 'page_error', text: err.message, stack: err.stack, timestamp: new Date().toISOString(), }); }); page.on('requestfailed', req => { networkErrors.push({ type: 'network_failure', url: req.url(), method: req.method(), failure: req.failure()?.errorText || 'unknown', resourceType: req.resourceType(), timestamp: new Date().toISOString(), }); }); page.on('response', res => { if (res.status() >= 400) { networkErrors.push({ type: 'http_error', url: res.url(), status: res.status(), statusText: res.statusText(), method: res.request().method(), resourceType: res.request().resourceType(), timestamp: new Date().toISOString(), }); } }); try { await page.goto(fullUrl, { waitUntil: 'networkidle', timeout: 30000 }); await page.waitForTimeout(1000); } finally { await page.close(); } return { pagePath, consoleErrors, networkErrors }; } async function main() { if (!TARGET_URL) { console.error('TARGET_URL environment variable is required'); process.exit(1); } const browser = await chromium.launch({ headless: true }); const context = await browser.newContext(); const results = []; try { for (const pagePath of PAGES) { try { const result = await monitorPage(context, pagePath); results.push(result); console.log(`Checked ${pagePath}: ${result.consoleErrors.length} console errors, ${result.networkErrors.length} network errors`); } catch (err) { results.push({ pagePath, error: err.message, consoleErrors: [], networkErrors: [] }); console.error(`Failed ${pagePath}: ${err.message}`); } } } finally { await browser.close(); } const totalConsoleErrors = results.reduce((sum, r) => sum + r.consoleErrors.length, 0); const totalNetworkErrors = results.reduce((sum, r) => sum + r.networkErrors.length, 0); const pagesWithErrors = results.filter(r => r.consoleErrors.length > 0 || r.networkErrors.length > 0).length; const report = { timestamp: new Date().toISOString(), targetUrl: TARGET_URL, pages: PAGES, summary: { totalPages: results.length, pagesWithErrors, totalConsoleErrors, totalNetworkErrors, hasErrors: totalConsoleErrors > 0 || totalNetworkErrors > 0, }, results, }; fs.mkdirSync(REPORTS_DIR, { recursive: true }); const reportPath = path.join(REPORTS_DIR, 'console-error-report.json'); fs.writeFileSync(reportPath, JSON.stringify(report, null, 2)); console.log(`Report saved to ${reportPath}`); if (totalConsoleErrors > 0 || totalNetworkErrors > 0) { console.error(`Found ${totalConsoleErrors} console errors and ${totalNetworkErrors} network errors across ${pagesWithErrors} page(s)`); process.exit(1); } } main().catch(err => { console.error('Fatal error:', err); process.exit(1); });