Visual Regression Testing
Visual regression testing detects unintended UI changes by comparing screenshots before and after code changes. It catches layout breaks, CSS bugs, and visual inconsistencies that unit tests miss completely.
How It Works
- Capture baseline screenshots of key pages
- Make code changes
- Capture new screenshots of the same pages
- Compare pixel-by-pixel with the baselines
- Flag pages where differences exceed a threshold
Implementation
import { PNG } from 'pngjs';
import pixelmatch from 'pixelmatch';
import fs from 'fs';
async function captureScreenshot(url) {
const res = await fetch(
`https://apisnap.dev/api/screenshot?url=${encodeURIComponent(url)}&width=1440&height=900`,
{ headers: { Authorization: `Bearer ${process.env.SNAPAPI_KEY}` } }
);
return Buffer.from(await res.arrayBuffer());
}
async function compareWithBaseline(url, baselinePath) {
const current = await captureScreenshot(url);
const baseline = fs.readFileSync(baselinePath);
const img1 = PNG.sync.read(baseline);
const img2 = PNG.sync.read(current);
const diff = new PNG({ width: img1.width, height: img1.height });
const numDiff = pixelmatch(
img1.data, img2.data, diff.data,
img1.width, img1.height,
{ threshold: 0.1 }
);
const percentDiff = (numDiff / (img1.width * img1.height)) * 100;
console.log(`Difference: ${percentDiff.toFixed(2)}%`);
if (percentDiff > 0.5) {
fs.writeFileSync('diff.png', PNG.sync.write(diff));
throw new Error(`Visual regression: ${percentDiff.toFixed(2)}% pixels differ`);
}
}CI/CD Integration
Add visual regression tests to your CI pipeline. Run them on every pull request to catch visual changes before they reach production. Store baseline screenshots in your repository or a dedicated storage bucket. Update baselines intentionally when designs change.