Jest ships with experimental support for Browser Mode. The implementation may have bugs and lack features.
Visual Regression Testing
Browser Mode includes built-in visual regression testing through toMatchScreenshot. It captures screenshots, compares them against reference images, and detects unintended visual changes.
Basic Usage
import {expect, it} from '@jest/globals';
it('component looks correct', async () => {
// render your component...
const element = document.querySelector('.my-component');
await expect(element).toMatchScreenshot('component-name');
});
Creating References
When you run a visual test for the first time, Jest creates a reference screenshot and fails the test:
expect(element).toMatchScreenshot()
No existing reference screenshot found; a new one was created.
Review it before running tests again.
Reference screenshot:
__screenshots__/my-test.test.ts/component-name-chromium-darwin.png
Review the screenshot, then run the test again. Jest will now compare future runs against this baseline.
__screenshots__ folders next to your tests. Commit them to version control. :::Screenshot Organization
.
├── __screenshots__/
│ └── test-file.test.ts/
│ ├── component-chromium-darwin.png
│ ├── component-firefox-linux.png
│ └── component-webkit-win32.png
└── test-file.test.ts
The naming convention includes:
- Name: the first argument to
toMatchScreenshot(), or auto-generated from the test name - Browser:
chromium,firefox, orwebkit - Platform:
darwin,linux, orwin32
Auto-Naming
When no name is given, screenshots are named from the test:
it('hero section', async () => {
await expect(element).toMatchScreenshot(); // → "hero section 1"
await expect(other).toMatchScreenshot(); // → "hero section 2"
});
Page-Level Screenshots
Pass page to capture the full page:
import {expect, it, page} from '@jest/globals';
it('full page', async () => {
await expect(page).toMatchScreenshot('full-page');
});
Masking Dynamic Content
Mask elements that change between runs (timestamps, avatars, etc.):
await expect(element).toMatchScreenshot('profile', {
screenshotOptions: {
mask: [document.querySelector('.timestamp')],
},
});
Configuration
Configure thresholds globally:
- JavaScript
const {defineConfig} = require('jest');
module.exports = defineConfig({
browserMode: {
enabled: true,
provider: 'playwright',
name: 'chromium',
screenshotDirectory: '__screenshots__',
screenshotFailures: true,
},
});
Or per-assertion:
await expect(element).toMatchScreenshot('text-heavy', {
threshold: 0.1, // pixel comparison threshold (0-1)
});
Debugging Failed Tests
When a visual test fails, Jest provides:
- Reference screenshot — the expected baseline
- Actual screenshot — what was captured
- Diff image — highlights differences
expect(element).toMatchScreenshot()
Screenshot does not match the stored reference.
245 pixels differ.
Reference: __screenshots__/button.test.ts/button-chromium-darwin.png
Actual: __diff__/button-chromium-darwin-actual.png
Diff: __diff__/button-chromium-darwin-diff.png
Best Practices
Test specific elements — capture components, not the full page, to reduce false positives:
// ❌ Captures entire page; prone to unrelated changes
await expect(page).toMatchScreenshot();
// ✅ Captures only the component under test
await expect(document.querySelector('.card')).toMatchScreenshot();
Disable animations — add CSS to your test setup:
*,
*::before,
*::after {
animation-duration: 0s !important;
transition-duration: 0s !important;
}
Set consistent viewport sizes — avoid flaky tests from responsive behavior:
{
"browserMode": {
"viewport": {"width": 1280, "height": 720}
}
}
Use Git LFS — store reference screenshots in Git LFS for large test suites.