Playwright’s screenshot capabilities go far beyond just capturing a static image; they’re a powerful tool for visual regression testing by enabling direct pixel-level comparison.
Let’s see Playwright in action, capturing a screenshot and then comparing it to a baseline.
First, we need to install Playwright if you haven’t already:
npm install playwright
Now, let’s write a simple test that navigates to a page, takes a screenshot, and saves it.
// example.spec.js
const { test, expect } = require('@playwright/test');
test('capture page screenshot', async ({ page }) => {
await page.goto('https://playwright.dev');
await page.screenshot({ path: 'playwright-home.png' });
});
When you run this with npx playwright test example.spec.js, it will create a playwright-home.png file in your project directory. This is the baseline.
To compare a new screenshot against this baseline, Playwright has built-in assertions. We’ll modify the test to take a new screenshot and assert that it matches the baseline.
// example.spec.js
const { test, expect } = require('@playwright/test');
test('compare page screenshot with baseline', async ({ page }) => {
await page.goto('https://playwright.dev');
// For a real test, you'd likely navigate to a different state or a new build
// Here we are just re-capturing to demonstrate the comparison
await expect(page).toHaveScreenshot('playwright-home.png', {
fullPage: true, // Capture the entire scrollable page
animations: 'disabled', // Ensure animations don't cause diffs
scale: 'css', // Match CSS pixel ratio
});
});
Running this test will compare the newly captured screenshot against playwright-home.png. If they differ, the test fails, and Playwright generates a diff image (e.g., playwright-home.png-diff.png) showing the exact pixel differences.
The core problem Playwright’s visual regression testing solves is detecting unintended visual changes in a web application. Traditional functional tests might verify that a button is clickable or that text is present, but they can’t tell you if a button’s color changed from blue to red, or if a layout shifted slightly, breaking the user experience. Visual regression testing catches these aesthetic or layout regressions automatically.
Internally, when toHaveScreenshot is used, Playwright does a few things:
- Captures a New Screenshot: It renders the current state of the page in the browser and captures an image.
- Locates the Baseline: It looks for the specified baseline image file (e.g.,
playwright-home.png). If it doesn’t exist, the test will fail, and Playwright will often prompt you to generate it. - Performs Pixel-by-Pixel Comparison: It compares the newly captured image with the baseline image, pixel by pixel.
- Generates a Diff Image: If any differences are found, it creates a new image highlighting these differences. This diff image is crucial for understanding what changed.
- Fails the Test: The assertion fails if any differences are detected.
The toHaveScreenshot matcher offers several options to fine-tune the comparison:
fullPage: Set totrueto capture the entire scrollable page, not just the viewport. This is essential for layouts that span beyond the initial view.animations: Set todisabledto prevent animations from causing false positives. Playwright waits for animations to settle before capturing.scale: Controls how the screenshot is scaled.cssensures it matches the CSS pixel ratio.clip: Allows you to capture only a specific region of the page.mask: You can mask specific elements (e.g., dynamic content like user avatars or timestamps) so they don’t cause diffs.
To effectively use this, you’ll typically have a workflow:
- Run your tests on a stable baseline environment.
- Capture and commit your baseline screenshots to version control.
- When you make changes, run the tests again.
- If the tests fail (due to visual changes), review the diff images.
- If the changes are intended, update your baseline screenshots. If they are unintended, fix the code.
A common pitfall is forgetting to update the baseline when a visual change is intentional. This leads to failing tests even though the application is working as designed. Playwright provides mechanisms to re-baseline your screenshots easily. After a test run fails with visual differences, you can update the baselines by running:
npx playwright test --update-snapshots
This command will replace the old baseline images with the newly captured ones. It’s vital to review these changes carefully before committing them.
The mask option is particularly powerful for handling dynamic content that you don’t want to affect your visual tests. You can pass a selector to mask to have Playwright cover that element with a solid color before comparison. For example, await expect(page).toHaveScreenshot({ mask: [page.locator('.user-avatar')] }); would mask any element with the class user-avatar.
The next logical step after mastering static visual regression is to explore how Playwright handles visual comparisons across different browsers and viewports, often managed through its configuration file.