home / skills / a5c-ai / babysitter / screenshot-comparison

This skill enables visual regression testing by capturing, comparing, and reporting pixel-perfect diffs across viewports to ensure UI consistency.

npx playbooks add skill a5c-ai/babysitter --skill screenshot-comparison

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
7.3 KB
---
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
---

# 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:

```javascript
// 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:

```javascript
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:

```javascript
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:

```json
{
  "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:

```bash
# 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:

```javascript
// 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](https://www.browserstack.com/docs/browserstack-mcp-server/tools/percy) |
| Playwright MCP Server | Browser automation with screenshots | [GitHub](https://github.com/executeautomation/mcp-playwright) |

## Best Practices

1. **Ignore dynamic content** - Hide timestamps, ads, animations before capture
2. **Use consistent environments** - Same browser version, OS, fonts
3. **Set appropriate thresholds** - Balance sensitivity vs false positives
4. **Organize baselines** - Clear naming convention and version control
5. **Review before approve** - Always review diffs before accepting
6. **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:

```json
{
  "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

Overview

This skill provides visual regression testing through deterministic screenshot capture and pixel-level comparison to ensure UI consistency across changes. It supports responsive captures across viewports, baseline management, and generates visual change reports with highlighted diffs. Use it to catch unintended visual regressions before they reach production.

How this skill works

The skill captures screenshots at page, element, or component level using a browser automation tool and can run across multiple viewports for responsive testing. It compares current screenshots against stored baselines with a pixel-diff engine (configurable threshold, antialiasing options) and produces diff images and quantitative diff percentages. Results are emitted as structured reports and can be integrated into CI/CD pipelines, approval workflows, or baseline update commands.

When to use it

  • Before merging UI changes to detect unintended visual regressions
  • During CI runs to enforce visual stability across branches
  • When validating responsive layouts across multiple breakpoints
  • For component-level testing in Storybook or isolated environments
  • When auditing changes that involve fonts, spacing, or images

Best practices

  • Hide or mask dynamic elements (timestamps, animations, ads) before capture
  • Run tests in consistent environments: same browser version, OS, and fonts
  • Set sensible diff thresholds to balance sensitivity and false positives
  • Organize baselines with clear naming and version control
  • Review diffs manually before approving baseline updates

Example use cases

  • Automated CI job that captures desktop and mobile screenshots and fails the build if diffs exceed a threshold
  • Component library regression: capture Storybook components and compare to baselines
  • Responsive regression sweep: capture across mobile, tablet, desktop, and wide viewports
  • Design-to-implementation check: compare design exports or prototypes against implemented pages
  • Baseline management workflow to approve or update failed comparisons

FAQ

What diff engine and options are supported?

Uses pixel-diff libraries like pixelmatch with configurable threshold, antialiasing handling, and diff highlight colors.

How do I reduce false positives from animations or fonts?

Hide or freeze dynamic elements before capture, run in controlled environments, and set tolerant thresholds for font rendering differences.