Playwright Snapshot Testing: Your Photo Album for Code
The Big Picture: What’s Snapshot Testing?
Imagine you take a photo of your room every day. If someone moves your teddy bear, you’ll notice because today’s photo looks different from yesterday’s!
Snapshot testing works the same way:
- You take a “photo” of your webpage
- Next time, Playwright compares the new “photo” to the old one
- If something changed, it tells you!
This helps catch visual bugs before your users see them.
🎯 The Camera Metaphor
Throughout this guide, think of snapshots as photographs:
| Concept | Camera Analogy |
|---|---|
toMatchSnapshot |
Taking a photo |
| Updating snapshots | Replacing old photos |
maxDiffPixels |
“Ignore tiny dust specks” |
threshold |
“Ignore small lighting changes” |
| ARIA snapshots | Photo of the room layout, not colors |
📸 toMatchSnapshot: Taking the First Photo
The toMatchSnapshot command captures what your page looks like.
// Take a snapshot of the page
await expect(page).toMatchSnapshot();
First run: Playwright saves a “baseline” image. Next runs: It compares new screenshots to that baseline.
Screenshot a Specific Element
// Just capture the button,
// not the whole page
const button = page.locator('button');
await expect(button).toMatchSnapshot();
Give Your Snapshot a Name
// Name it so you can find it later
await expect(page).toMatchSnapshot(
'homepage-hero.png'
);
Why name it? Like labeling photos in an album—easier to find!
🔄 Updating Snapshots: When Change is Good
Sometimes you want the page to look different. Maybe you redesigned the button!
Problem: The old snapshot says “This doesn’t match!”
Solution: Tell Playwright to take a new baseline photo.
npx playwright test --update-snapshots
This command says: “The new look is correct. Save it!”
When to Update
✅ Update when:
- You intentionally changed the design
- You added new features
- You fixed a visual bug
❌ Don’t update when:
- You’re not sure why it changed
- The change looks wrong
⚙️ Snapshot Configuration: Camera Settings
Just like a camera has settings (brightness, focus), snapshots have options too!
Basic Configuration in playwright.config.js
export default {
expect: {
toMatchSnapshot: {
// How different can pixels be?
threshold: 0.2,
// How many pixels can differ?
maxDiffPixels: 100,
},
},
};
Per-Test Configuration
await expect(page).toMatchSnapshot({
maxDiffPixels: 50,
threshold: 0.3,
});
🔍 maxDiffPixels: “How Many Specks of Dust?”
Imagine comparing two photos. One has 3 tiny dust specks. Should you worry?
maxDiffPixels says: “Ignore up to X different pixels”
// Allow up to 100 pixels to differ
await expect(page).toMatchSnapshot({
maxDiffPixels: 100,
});
When to Use
| Pixels | Good For |
|---|---|
| 0-50 | Strict matching |
| 50-200 | Minor rendering differences |
| 200+ | Screens with animations |
Example: A blinking cursor might change 20 pixels. Set maxDiffPixels: 30 to ignore it.
🎚️ threshold: “How Different is Different?”
This controls how similar two pixels must be to count as “the same.”
Think of it like squinting at two paint colors:
- threshold: 0 → “Those are NOT the same blue!”
- threshold: 0.5 → “Eh, close enough!”
await expect(page).toMatchSnapshot({
threshold: 0.2, // 0 to 1 scale
});
Visual Guide
threshold: 0.0 → Perfect match only
threshold: 0.1 → Tiny color shifts OK
threshold: 0.2 → Default, good balance
threshold: 0.5 → Very forgiving
threshold: 1.0 → Everything matches!
Real Example
// Anti-aliasing causes slight color
// differences at edges. Allow it:
await expect(button).toMatchSnapshot({
threshold: 0.25,
});
♿ ARIA Snapshots: The Blueprint, Not the Paint
Regular snapshots capture how things look.
ARIA snapshots capture how things are structured for screen readers.
Think of it as photographing the blueprint of a house, not the paint color.
// Capture accessibility structure
await expect(page.locator('nav'))
.toMatchAriaSnapshot();
Why ARIA Snapshots Matter
They ensure your app is accessible to:
- Screen reader users
- Keyboard-only users
- People using assistive technology
🏗️ toMatchAriaSnapshot: Accessibility Testing
This assertion captures the accessibility tree—a simplified structure of your page.
// Capture what a screen reader "sees"
await expect(
page.locator('form')
).toMatchAriaSnapshot();
What It Captures
- role: form
- role: textbox
name: "Email"
- role: textbox
name: "Password"
- role: button
name: "Submit"
Inline Snapshot Matching
await expect(page.locator('nav'))
.toMatchAriaSnapshot(`
- navigation:
- link "Home"
- link "About"
- link "Contact"
`);
Updating ARIA Snapshots
Same command as visual snapshots:
npx playwright test --update-snapshots
🗺️ The Complete Flow
graph TD A["Run Test First Time"] --> B["No Snapshot Exists"] B --> C["Create Baseline Snapshot"] C --> D["Test Passes"] E["Run Test Again"] --> F["Snapshot Exists"] F --> G{Compare Screenshots} G -->|Match| H["Test Passes"] G -->|Differ| I{Intentional?} I -->|Yes| J["Update Snapshot"] I -->|No| K["Fix the Bug!"] J --> H
💡 Quick Tips
Tip 1: Stable Selectors
// Good: Specific element
await expect(
page.getByRole('banner')
).toMatchSnapshot();
// Risky: Whole page
// (more can change)
await expect(page).toMatchSnapshot();
Tip 2: Handle Dynamic Content
// Hide dynamic elements first
await page.evaluate(() => {
document.querySelector('.timestamp')
.style.visibility = 'hidden';
});
await expect(page).toMatchSnapshot();
Tip 3: Combine Options
await expect(page).toMatchSnapshot({
maxDiffPixels: 100,
threshold: 0.2,
});
🎯 Summary: Your Snapshot Toolkit
| Tool | What It Does |
|---|---|
toMatchSnapshot() |
Captures visual screenshot |
--update-snapshots |
Saves new baseline |
maxDiffPixels |
Allows X pixels to differ |
threshold |
Allows color variations |
toMatchAriaSnapshot() |
Captures accessibility tree |
🚀 You’re Ready!
Snapshot testing is like having a quality inspector that:
- Never forgets what your app should look like
- Catches visual bugs before users do
- Ensures accessibility stays consistent
Start small—snapshot one important component—and grow from there!
Remember: A snapshot test passing means “This looks like it should.” A failure means “Something changed—let’s investigate!”
