| name | screenshot-comparison |
| description | Visual regression testing through screenshot capture and comparison. Pixel-diff analysis, responsive screenshot capture across viewports, and visual change reporting with highlighted differences. |
| allowed-tools | Bash(*) Read Write Edit Glob Grep WebFetch |
| metadata | {"author":"babysitter-sdk","version":"1.0.0","category":"visual-testing","backlog-id":"SK-UX-005"} |
| graph | {"domains":["domain:web-development"],"specializations":["specialization:ux-ui-design"],"skillAreas":["skill-area:visual-regression-testing","skill-area:ui-testing"],"roles":["role:qa-engineer","role:frontend-engineer"],"workflows":["workflow:user-feedback-loop","workflow:product-discovery"],"topics":["topic:responsive-design"]} |
screenshot-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)
pixelmatch or similar diff library
- Optional: Percy, Chromatic for cloud-based testing
Capabilities
1. Screenshot Capture
Capture screenshots with various configurations:
const screenshot = await page.screenshot({
fullPage: true,
path: 'screenshots/home-full.png'
});
const element = await page.locator('.hero-section');
await element.screenshot({ path: 'screenshots/hero.png' });
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({ path: 'screenshots/home-mobile.png' });
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,
includeAA: false,
diffColor: [255, 0, 0],
diffColorAlt: [0, 255, 0]
}
);
fs.writeFileSync('diff.png', PNG..(diff));
diffPercentage = (numDiffPixels / (width * height)) * ;
.();
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"
5. Baseline Management
Manage screenshot baselines:
/skill screenshot-comparison update-baseline \
--test header-mobile \
--approve
/skill screenshot-comparison update-baseline \
--all-failed \
--approve
/skill screenshot-comparison review \
--status pending
6. Component-Level Testing
Test individual components in isolation:
const stories = await getStorybookStories();
for (const story of stories) {
await page.goto(`${storybookUrl}/iframe.html?id=${story.id}`);
await page.waitForSelector('#storybook-root > *');
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-library.js - Component visual regression
responsive-design.js - Responsive visual testing
hifi-prototyping.js - Design-to-implementation comparison
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