Visual regression testing captures screenshots and compares them against baseline images to detect unintended UI changes. Tools like Percy, Chromatic, or Playwright screenshots help catch CSS regressions. Best for component libraries and design systems.
How It Works:
Popular Tools:
Best Practices:
// visual.spec.js
import { test, expect } from '@playwright/test';
test.describe('Visual Regression', () => {
test('homepage matches snapshot', async ({ page }) => {
await page.goto('/');
// Wait for content to load
await page.waitForLoadState('networkidle');
// Full page screenshot comparison
await expect(page).toHaveScreenshot('homepage.png', {
fullPage: true,
maxDiffPixels: 100, // Allow small differences
});
});
test('button component states', async ({ page }) => {
await page.goto('/components/button');
// Screenshot specific element
const button = page.locator('.primary-button');
await expect(button).toHaveScreenshot('button-default.png');
// Hover state
await button.hover();
await expect(button).toHaveScreenshot('button-hover.png');
// Focus state
await button.focus();
await expect(button).toHaveScreenshot('button-focus.png');
});
test('responsive layouts', async ({ page }) => {
await page.goto('/products');
// Test multiple viewports
const viewports = [
{ width: 1920, height: 1080, name: 'desktop' },
{ width: 768, height: 1024, name: 'tablet' },
{ width: 375, height: 667, name: 'mobile' },
];
for (const viewport of viewports) {
await page.setViewportSize({ width: viewport.width, height: viewport.height });
await expect(page).toHaveScreenshot(`products-${viewport.name}.png`);
}
});
});