</>

Technology

Playwright

Difficulty

Advanced

Interview Question

What is visual regression testing in Playwright and how do you implement it?

Answer

Visual Regression Testing in Playwright

Visual regression testing catches unexpected visual changes by comparing screenshots to baseline images.

Basic Screenshot Comparison

TypeScript
import { test, expect } from '@playwright/test';

test('homepage looks correct', async ({ page }) => {
  await page.goto('/');

  // Compare full page to baseline
  await expect(page).toHaveScreenshot('homepage.png');
});

test('button styles are correct', async ({ page }) => {
  await page.goto('/design-system');

  // Compare a specific element
  await expect(page.locator('.button-group')).toHaveScreenshot('buttons.png');
});

First Run — Creates Baseline

Bash
# First run generates baseline images in __snapshots__/
npx playwright test

Subsequent Runs — Compare to Baseline

Any pixel difference above threshold fails the test:

CODE
Error: Screenshot comparison failed:
Expected: homepage.png
Received: homepage-actual.png
Diff: 234 pixels changed (0.3%)

Update Baselines

Bash
# Regenerate all baselines
npx playwright test --update-snapshots

Configuration Options

TypeScript
// playwright.config.ts
export default defineConfig({
  expect: {
    toHaveScreenshot: {
      maxDiffPixels: 100,        // Allow up to 100 different pixels
      maxDiffPixelRatio: 0.01,   // Allow up to 1% pixel difference
      threshold: 0.2,            // Color distance threshold (0-1)
      animations: 'disabled',   // Disable CSS animations before screenshot
    },
  },
});

Masking Dynamic Areas

TypeScript
// Ignore areas that change (timestamps, ads, etc.)
await expect(page).toHaveScreenshot('dashboard.png', {
  mask: [
    page.locator('.timestamp'),
    page.locator('.live-count'),
    page.locator('#ad-banner'),
  ],
});

Full Visual Test Suite

TypeScript
import { test, expect } from '@playwright/test';

const pages = [
  { name: 'home',       path: '/' },
  { name: 'login',      path: '/login' },
  { name: 'dashboard',  path: '/dashboard' },
  { name: 'products',   path: '/products' },
];

for (const { name, path } of pages) {
  test(`${name} page visual regression`, async ({ page }) => {
    await page.goto(path);

    // Wait for animations to settle
    await page.waitForLoadState('networkidle');

    await expect(page).toHaveScreenshot(`${name}.png`, {
      fullPage: true,
      animations: 'disabled',
    });
  });
}

Folder Structure for Snapshots

CODE
tests/
├── visual/
│   └── homepage.spec.ts
└── __snapshots__/
    └── visual/
        ├── homepage.spec.ts-snapshots/
        │   ├── homepage-chromium-darwin.png    # Platform-specific baselines
        │   ├── homepage-firefox-darwin.png
        │   └── homepage-webkit-darwin.png

Important: Visual baselines are OS and browser-specific. CI and local machines often differ — create and update baselines in CI to avoid false failures.

Follow AutomateQA

Related Topics