- Redesign PreJoin component and CSS for improved template compatibility and deterministic rendering - Remove mock studio toggle and related runtime logic; update useStudioLauncher to always use real backend - Add README-MOCK.md to document mock studio deprecation - Add mock-studio.html for manual popup emulation - Update environment variable resolution in route.ts for backend API - Add visual regression test scripts (capture, compare, visual_test_prejoin) using Playwright, Puppeteer, pixelmatch, and pngjs - Update package.json scripts and devDependencies for visual testing - Simplify PreJoin.stories.tsx for robust Storybook usage
65 lines
3.0 KiB
JavaScript
65 lines
3.0 KiB
JavaScript
#!/usr/bin/env node
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const puppeteer = require('puppeteer');
|
|
const PNG = require('pngjs').PNG;
|
|
const pixelmatch = require('pixelmatch');
|
|
|
|
async function capture(fileUrl, outPath, width=1280, height=720) {
|
|
const browser = await puppeteer.launch({args: ['--no-sandbox','--disable-setuid-sandbox']});
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width, height });
|
|
await page.goto(fileUrl, { waitUntil: 'networkidle0' });
|
|
// wait a bit for scripts to run
|
|
await page.waitForTimeout(500);
|
|
await page.screenshot({ path: outPath, fullPage: false });
|
|
await browser.close();
|
|
}
|
|
|
|
function compare(imgAPath, imgBPath, diffOut) {
|
|
const imgA = PNG.sync.read(fs.readFileSync(imgAPath));
|
|
const imgB = PNG.sync.read(fs.readFileSync(imgBPath));
|
|
if (imgA.width !== imgB.width || imgA.height !== imgB.height) {
|
|
throw new Error('Images must have same dimensions');
|
|
}
|
|
const { width, height } = imgA;
|
|
const diff = new PNG({ width, height });
|
|
const mismatched = pixelmatch(imgA.data, imgB.data, diff.data, width, height, { threshold: 0.1 });
|
|
fs.writeFileSync(diffOut, PNG.sync.write(diff));
|
|
return { mismatched, total: width*height, ratio: mismatched / (width*height) };
|
|
}
|
|
|
|
(async () => {
|
|
try {
|
|
const outDir = '/tmp';
|
|
const fileArg = process.argv[2] || `file://${path.resolve(process.cwd(),'docs/prejoin_template.html')}`;
|
|
const outFile = path.join(outDir, 'prejoin_capture_1280x720.png');
|
|
console.log('Capturing', fileArg, '->', outFile);
|
|
await capture(fileArg, outFile, 1280, 720);
|
|
console.log('Saved capture to', outFile);
|
|
// If baseline exists in repo root under baselines/, compare
|
|
const baselineA = path.resolve(process.cwd(), 'baselines/prejoin_regen_1280x720.png');
|
|
const baselineB = path.resolve(process.cwd(), 'baselines/prejoin_browserless_1280x720.png');
|
|
let result = { captured: outFile, compared: false };
|
|
if (fs.existsSync(baselineA)) {
|
|
const diffOut = path.join(outDir, 'prejoin_diff_1280x720.png');
|
|
const metrics = compare(outFile, baselineA, diffOut);
|
|
result.compared = true; result.baseline = baselineA; result.diff = diffOut; result.metrics = metrics;
|
|
console.log('Compared with', baselineA, 'metrics=', metrics);
|
|
} else if (fs.existsSync(baselineB)) {
|
|
const diffOut = path.join(outDir, 'prejoin_diff_1280x720.png');
|
|
const metrics = compare(outFile, baselineB, diffOut);
|
|
result.compared = true; result.baseline = baselineB; result.diff = diffOut; result.metrics = metrics;
|
|
console.log('Compared with', baselineB, 'metrics=', metrics);
|
|
} else {
|
|
console.log('No baseline found (checked baselines/prejoin_regen_1280x720.png and baselines/prejoin_browserless_1280x720.png)');
|
|
}
|
|
fs.writeFileSync(path.join('/tmp','prejoin_capture_report.json'), JSON.stringify(result, null, 2));
|
|
console.log('Report written to /tmp/prejoin_capture_report.json');
|
|
} catch (err) {
|
|
console.error('Failed:', err);
|
|
process.exit(2);
|
|
}
|
|
})();
|
|
|