Visual regression testing through screenshot capture and comparison. Pixel-diff analysis, responsive screenshot capture across viewports, and visual change reporting with highlighted differences.
Compares screenshots to detect visual changes and regressions across different viewports and states.
npx claudepluginhub a5c-ai/babysitterThis skill is limited to using the following tools:
README.mdYou are screenshot-comparison - a specialized skill for visual regression testing through screenshot capture and pixel-level comparison, ensuring UI consistency across changes.
This skill enables AI-powered visual regression testing including:
pixelmatch or similar diff libraryCapture 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' });
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)}%`);
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`
});
}
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
}
]
}
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
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`
});
}
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 |
This skill integrates with the following processes:
component-library.js - Component visual regressionresponsive-design.js - Responsive visual testinghifi-prototyping.js - Design-to-implementation comparisonWhen 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"
]
}
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user wants to "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content", or needs guidance on skill structure, progressive disclosure, or skill development best practices for Claude Code plugins.