Babysitter screenshot-comparison
Visual regression testing through screenshot capture and comparison. Pixel-diff analysis, responsive screenshot capture across viewports, and visual change reporting with highlighted differences.
git clone https://github.com/a5c-ai/babysitter
T=$(mktemp -d) && git clone --depth=1 https://github.com/a5c-ai/babysitter "$T" && mkdir -p ~/.claude/skills && cp -r "$T/library/specializations/ux-ui-design/skills/screenshot-comparison" ~/.claude/skills/a5c-ai-babysitter-screenshot-comparison && rm -rf "$T"
library/specializations/ux-ui-design/skills/screenshot-comparison/SKILL.mdscreenshot-comparison
You are screenshot-comparison - a specialized skill for visual regression testing through screenshot capture and pixel-level comparison, ensuring UI consistency across changes.
Overview
This skill enables AI-powered visual regression testing including:
- Capturing component and page screenshots
- Pixel-diff comparison with configurable thresholds
- Responsive screenshot capture across breakpoints
- Visual change reporting with highlighted differences
- Baseline management and approval workflows
- Integration with CI/CD pipelines
Prerequisites
- Node.js 18+ installed
- Browser automation tool (Playwright, Puppeteer)
or similar diff librarypixelmatch- Optional: Percy, Chromatic for cloud-based testing
Capabilities
1. Screenshot Capture
Capture screenshots with various configurations:
// Full page screenshot const screenshot = await page.screenshot({ fullPage: true, path: 'screenshots/home-full.png' }); // Element screenshot const element = await page.locator('.hero-section'); await element.screenshot({ path: 'screenshots/hero.png' }); // Viewport-specific screenshot await page.setViewportSize({ width: 375, height: 667 }); await page.screenshot({ path: 'screenshots/home-mobile.png' }); // Hide dynamic elements await page.evaluate(() => { document.querySelectorAll('[data-testid="timestamp"]') .forEach(el => el.style.visibility = 'hidden'); }); await page.screenshot({ path: 'screenshots/home-stable.png' });
2. Pixel-Diff Comparison
Compare screenshots and generate diff images:
const pixelmatch = require('pixelmatch'); const { PNG } = require('pngjs'); const fs = require('fs'); const baseline = PNG.sync.read(fs.readFileSync('baseline.png')); const current = PNG.sync.read(fs.readFileSync('current.png')); const { width, height } = baseline; const diff = new PNG({ width, height }); const numDiffPixels = pixelmatch( baseline.data, current.data, diff.data, width, height, { threshold: 0.1, // Sensitivity (0-1) includeAA: false, // Ignore antialiasing diffColor: [255, 0, 0], // Diff highlight color diffColorAlt: [0, 255, 0] // Alt color for anti-aliased } ); fs.writeFileSync('diff.png', PNG.sync.write(diff)); const diffPercentage = (numDiffPixels / (width * height)) * 100; console.log(`Diff: ${diffPercentage.toFixed(2)}%`);
3. Responsive Testing
Capture screenshots across multiple viewports:
const viewports = [ { name: 'mobile', width: 375, height: 667 }, { name: 'tablet', width: 768, height: 1024 }, { name: 'desktop', width: 1440, height: 900 }, { name: 'wide', width: 1920, height: 1080 } ]; const results = []; for (const viewport of viewports) { await page.setViewportSize({ width: viewport.width, height: viewport.height }); await page.screenshot({ path: `screenshots/${pageName}-${viewport.name}.png`, fullPage: true }); results.push({ viewport: viewport.name, path: `screenshots/${pageName}-${viewport.name}.png` }); }
4. Visual Change Report
Generate comprehensive diff reports:
{ "testRun": { "id": "vr-2026-01-24-001", "timestamp": "2026-01-24T10:30:00Z", "branch": "feature/new-header", "commit": "abc123" }, "summary": { "total": 25, "passed": 22, "failed": 2, "new": 1, "passRate": "88%" }, "comparisons": [ { "name": "homepage-desktop", "status": "passed", "diffPercentage": 0.01, "threshold": 0.1, "baseline": "baseline/homepage-desktop.png", "current": "current/homepage-desktop.png" }, { "name": "header-mobile", "status": "failed", "diffPercentage": 5.2, "threshold": 0.1, "baseline": "baseline/header-mobile.png", "current": "current/header-mobile.png", "diff": "diffs/header-mobile-diff.png", "changedRegions": [ { "x": 10, "y": 5, "width": 200, "height": 50, "description": "Logo area" } ] }, { "name": "new-feature-banner", "status": "new", "current": "current/new-feature-banner.png", "requiresApproval": true } ] }
5. Baseline Management
Manage screenshot baselines:
# Update baseline for specific test /skill screenshot-comparison update-baseline \ --test header-mobile \ --approve # Update all failed baselines /skill screenshot-comparison update-baseline \ --all-failed \ --approve # Review pending approvals /skill screenshot-comparison review \ --status pending
6. Component-Level Testing
Test individual components in isolation:
// Storybook integration const stories = await getStorybookStories(); for (const story of stories) { // Navigate to story await page.goto(`${storybookUrl}/iframe.html?id=${story.id}`); // Wait for component await page.waitForSelector('#storybook-root > *'); // Capture component screenshot const component = await page.locator('#storybook-root > *'); await component.screenshot({ path: `screenshots/components/${story.id}.png` }); }
MCP Server Integration
This skill can leverage the following MCP servers:
| Server | Description | Installation |
|---|---|---|
| Percy via BrowserStack MCP | Cloud-based visual testing | BrowserStack |
| Playwright MCP Server | Browser automation with screenshots | GitHub |
Best Practices
- Ignore dynamic content - Hide timestamps, ads, animations before capture
- Use consistent environments - Same browser version, OS, fonts
- Set appropriate thresholds - Balance sensitivity vs false positives
- Organize baselines - Clear naming convention and version control
- Review before approve - Always review diffs before accepting
- Test critical paths - Focus on high-impact user journeys
Process Integration
This skill integrates with the following processes:
- Component visual regressioncomponent-library.js
- Responsive visual testingresponsive-design.js
- Design-to-implementation comparisonhifi-prototyping.js
Output Format
When executing operations, provide structured output:
{ "operation": "compare", "status": "completed", "summary": { "total": 10, "passed": 9, "failed": 1 }, "results": [ { "name": "header-desktop", "status": "passed", "diffPercentage": 0.02 } ], "artifacts": [ "report.html", "diffs/header-mobile-diff.png" ] }
Error Handling
- Handle page load failures gracefully
- Report element not found errors
- Manage baseline not found scenarios
- Provide clear diff visualization
Constraints
- Screenshots may vary across browsers/OS
- Animations and transitions cause false positives
- Large pages may require chunked capture
- Font rendering differences require tolerance