- Add docker-compose.web-testing.yml with vlmkit service - Add 5 test scripts: capture, compare, pipeline, console-monitor, link-checker - Add vrt.config.json with 3 viewports + maskSelectors - Add package.json with @mizchi/vlmkit and Node >=24 - Add tests/README.md with VRT documentation - Update .gitignore for test artifacts Based on APAW issue #144 / milestone #106
128 lines
3.7 KiB
JavaScript
128 lines
3.7 KiB
JavaScript
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);
|
|
});
|