← Back to Tutorials

12. Visual Testing

Screenshots

// Full page screenshot
await page.screenshot({ path: 'screenshots/full-page.png', fullPage: true });

// Element screenshot
await page.locator('.header').screenshot({ path: 'screenshots/header.png' });

// Screenshot with mask (hide dynamic content)
await page.screenshot({
  path: 'screenshots/dashboard.png',
  mask: [page.locator('.user-avatar')]
});

Screenshot Assertions (Visual Diff)

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

test('visual comparison', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('homepage.png', {
    maxDiffPixels: 100,
    threshold: 0.2,  // 0-1, lower = stricter
  });
});

// Update baseline snapshots
// npx playwright test --update-snapshots

Visual Diff Algorithms

StrategyDescriptionWhen to Use
Pixel-by-pixelCompare every pixelStrict comparisons
ThresholdAllow small color differencesCross-browser testing
Max diff pixelsAllow N pixels to differAnimations, timestamps
MaskExclude regions from diffDynamic content areas

Config for Visual Testing

// playwright.config.ts
use: {
  screenshot: 'only-on-failure',
  // OR
  screenshot: 'on',
}
// For visual tests, set:
expect: {
  toHaveScreenshot: {
    maxDiffPixels: 200,
    stylePath: './visual-overrides.css',
  }
}
✏️ Exercise: Take a screenshot of a page, make a small CSS change (e.g., change a button color), re-run the visual test, and observe the diff output.