Comprehensive visual regression testing using Playwright and jest-image-snapshot...
This skill provides comprehensive visual regression testing capabilities to detect unintended visual changes in UI components and prevent visual bugs from being merged into production.
Visual regression testing works by:
Framework: Playwright + jest-image-snapshot Approach: Based on Ant Design's visual regression testing methodology
Create and update baseline screenshots that serve as the source of truth for visual comparison.
Implementation: tests/shared/imageTest.tsx
Key features:
Implementation: scripts/visual-regression/
Core testing workflow:
// Example structure from tests/shared/imageTest.tsx
import { test, expect } from '@playwright/test';
test('component visual regression', async ({ page }) => {
await page.goto('http://localhost:5173/component-demo');
await page.waitForLoadState('networkidle');
// Take screenshot and compare with baseline
const screenshot = await page.screenshot();
expect(screenshot).toMatchImageSnapshot({
customSnapshotsDir: '__image_snapshots__',
customDiffDir: '__image_snapshots__/diff',
threshold: 0.1, // 0.1% pixel difference tolerance
});
});
Implementation: .github/workflows/visual-regression-*.yml
Workflow files:
visual-regression-pr.yml - Runs on pull requestsvisual-regression-baseline.yml - Updates baselines on main branchvisual-regression-report.yml - Generates and uploads diff reportsPR Workflow:
Baseline Update Workflow:
.github/workflows/
├── visual-regression-pr.yml # PR visual checks
├── visual-regression-baseline.yml # Baseline updates
└── visual-regression-report.yml # Diff reporting
tests/shared/
└── imageTest.tsx # Baseline screenshot utilities
scripts/visual-regression/
├── capture-baselines.ts # Generate baseline screenshots
├── compare-screenshots.ts # Compare current vs baseline
├── generate-report.ts # Create HTML diff report
└── upload-to-storage.ts # Upload to OSS/S3
__image_snapshots__/
├── baseline/ # Baseline screenshots
├── current/ # Latest test screenshots
└── diff/ # Difference highlights
When developing a new component:
# 1. Create component and demos
npm run dev
# 2. Generate initial baseline
npm run visual:baseline
# 3. Make changes
# ... edit component code ...
# 4. Run visual regression test
npm run visual:test
# 5. Review diffs (if any)
npm run visual:report
# 6. Update baseline if changes are intentional
npm run visual:update-baseline
Reviewers can:
# Example from .github/workflows/visual-regression-pr.yml
name: Visual Regression Testing
on:
pull_request:
branches: [main, develop]
jobs:
visual-regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps chromium
- name: Start dev server
run: npm run dev &
- name: Wait for server
run: npx wait-on http://localhost:5173
- name: Run visual regression tests
run: npm run visual:test
- name: Upload diff artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: visual-diffs
path: __image_snapshots__/diff/
- name: Generate report
if: failure()
run: npm run visual:report
- name: Comment PR with results
if: failure()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('visual-report.md', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: report
});
page.waitForLoadState('networkidle')// Strict comparison for critical UI
expect(screenshot).toMatchImageSnapshot({ threshold: 0.01 });
// Relaxed for minor anti-aliasing differences
expect(screenshot).toMatchImageSnapshot({ threshold: 0.1 });
// Very relaxed for charts/animations
expect(screenshot).toMatchImageSnapshot({ threshold: 0.5 });
Common causes of false positives:
Solutions:
Visual regression testing complements existing testing strategies:
Unit Tests (Jest)
↓
Component Tests (React Testing Library)
↓
Visual Regression (Playwright + jest-image-snapshot)
↓
E2E Tests (Playwright)
↓
Manual QA
Cause: Platform-specific rendering differences Solution:
expect(screenshot).toMatchImageSnapshot({
failureThreshold: 0.01,
failureThresholdType: 'percent'
});
Cause: Library update changed component styling Solution:
# Review changes first
npm run visual:test
# Update all baselines if changes are expected
npm run visual:update-baseline
Cause: Different environments (fonts, OS, browser version) Solution: Use Docker or GitHub Actions locally
# Run in Docker matching CI environment
docker run -v $(pwd):/app -w /app mcr.microsoft.com/playwright:v1.40.0 npm run visual:test
.github/workflows/visual-regression-*.yml - CI/CD workflowstests/shared/imageTest.tsx - Baseline screenshot implementationscripts/visual-regression/ - Test code and utilities// Test across Chromium, Firefox, and WebKit
import { devices } from '@playwright/test';
const browsers = ['chromium', 'firefox', 'webkit'];
for (const browser of browsers) {
test(`visual regression on ${browser}`, async ({ playwright }) => {
const browserInstance = await playwright[browser].launch();
const page = await browserInstance.newPage();
// ... test logic
});
}
// Test multiple viewports
const viewports = [
{ width: 375, height: 667, name: 'mobile' },
{ width: 768, height: 1024, name: 'tablet' },
{ width: 1920, height: 1080, name: 'desktop' },
];
for (const viewport of viewports) {
test(`visual regression ${viewport.name}`, async ({ page }) => {
await page.setViewportSize(viewport);
// ... test logic
});
}
// Test individual component variants
const variants = ['default', 'primary', 'danger', 'disabled'];
for (const variant of variants) {
test(`button ${variant} variant`, async ({ page }) => {
await page.goto(`http://localhost:5173/button/${variant}`);
await page.waitForLoadState('networkidle');
const screenshot = await page.locator('[data-testid="button"]').screenshot();
expect(screenshot).toMatchImageSnapshot({
customSnapshotIdentifier: `button-${variant}`
});
});
}
When users request visual regression testing, the agent should:
Setup Infrastructure
Generate Tests
Integrate with CI/CD
Provide Documentation
See the following files for complete implementation examples:
.github/workflows/visual-regression-pr.yml:1 - Full PR workflowtests/shared/imageTest.tsx:1 - Baseline screenshot utilitiesscripts/visual-regression/compare-screenshots.ts:1 - Comparison logicThis skill enables comprehensive visual regression testing that catches visual bugs before they reach production, maintaining UI consistency across the entire application.