A self-hosted visual regression testing tool built with Node.js that allows you to set baselines and compare screenshots of your website across different URLs and selectors.
- πΈ Screenshot capture with Puppeteer
- π Pixel-level image comparison with Pixelmatch
- π Console and HTML reporting
- βοΈ Flexible configuration for multiple URLs and selectors
- π― Support for different viewport sizes
- π Baseline management system
- π Easy-to-use CLI interface
- Clone or download this project
- Install dependencies:
npm install- Initialize configuration:
node index.js init- Edit the configuration file (
config/visual-regression.config.json) to match your website:
{
"baseUrl": "http://localhost:3000",
"targets": [
{
"name": "homepage",
"url": "/",
"selector": "body",
"viewport": { "width": 1200, "height": 800 }
},
{
"name": "header",
"url": "/",
"selector": "header",
"viewport": { "width": 1200, "height": 200 }
}
],
"options": {
"waitTime": 3000,
"threshold": 0.1,
"includeAA": false,
"diffMask": [255, 0, 255]
}
}- Set baseline screenshots:
node index.js baseline- Run visual regression tests:
node index.js test --htmlInitialize a sample configuration file.
node index.js init [--force]--force: Overwrite existing configuration
Crawl a website to auto-discover pages and generate configuration.
node index.js crawl <url> [--depth <number>] [--pages <number>] [--selector <selector>] [--save]<url>: Base URL to crawl (e.g., http://localhost:3000)--depth: Max crawl depth (default: 2)--pages: Max pages to find (default: 20)--selector: CSS selector to target on each page (default: body)--output: Output file for discovered targets (JSON)--save: Save found targets to config/visual-regression.config.json
Setup CI/CD integration.
node index.js ci --gitlab--gitlab: Generate a .gitlab-ci.yml file
Set baseline screenshots for comparison.
node index.js baseline [--config <path>] [--target <name>]--config: Configuration file path (default: config/visual-regression.config.json)--target: Set baseline for specific target only
Run visual regression tests.
node index.js test [--config <path>] [--output <dir>] [--html]--config: Configuration file path (default: config/visual-regression.config.json)--output: Output directory for results (default: results)--html: Generate HTML report
List all baseline screenshots.
node index.js listClear all baseline screenshots.
node index.js clear [--yes]--yes: Skip confirmation prompt
The configuration file (config/visual-regression.config.json) supports the following options:
The base URL for your website (e.g., http://localhost:3000).
Array of targets to test. Each target can have:
name: Unique identifier for the targeturl: URL path relative to baseUrlselector: CSS selector to capture (e.g.,body,#main,.header)viewport: Object withwidthandheightfor browser viewportignoreSelectors: Array of CSS selectors to hide (visibility: hidden)maskSelectors: Array of CSS selectors to mask with solid color
Comparison and capture options:
waitTime: Time to wait after page load before screenshot (ms)threshold: Difference threshold (0-1, lower = stricter)includeAA: Include anti-aliased pixels in comparisondiffMask: RGB color for highlighting differences
- Setup: Configure your targets in the config file
- Baseline: Capture initial screenshots as the "golden" baseline
- Develop: Make changes to your website
- Test: Run regression tests to compare against baseline
- Review: Check console output and HTML report for differences
- Update: If changes are expected, update the baseline
results/
βββ current-YYYY-MM-DDTHH-MM-SS-SSSZ/ # Current screenshots
βββ diff-YYYY-MM-DDTHH-MM-SS-SSSZ/ # Difference images
βββ report-YYYY-MM-DDTHH-MM-SS-SSSZ.html # HTML report
baseline/ # Baseline screenshots
{
"targets": [
{
"name": "homepage-desktop",
"url": "/",
"selector": "body",
"viewport": { "width": 1200, "height": 800 }
},
{
"name": "homepage-mobile",
"url": "/",
"selector": "body",
"viewport": { "width": 375, "height": 667 }
}
]
}{
"targets": [
{
"name": "navigation",
"url": "/",
"selector": "nav",
"viewport": { "width": 1200, "height": 100 }
},
{
"name": "footer",
"url": "/",
"selector": "footer",
"viewport": { "width": 1200, "height": 200 }
}
]
}{
"targets": [
{
"name": "home",
"url": "/",
"selector": "body",
"viewport": { "width": 1200, "height": 800 }
},
{
"name": "about",
"url": "/about",
"selector": "body",
"viewport": { "width": 1200, "height": 800 }
}
]
}This tool can be easily integrated into CI/CD pipelines:
# Set baseline (run once or when updating)
node index.js baseline
# Run tests in CI
node index.js test --html
# The tool will exit with code 1 if any tests fail- Screenshots are blank: Increase
waitTimein configuration - Element not found: Check that the selector exists and the page is fully loaded
- Connection refused: Ensure your website is running on the specified baseUrl
- Permission denied: Check file permissions for the project directory
For debugging, you can modify the screenshot-capture.js to enable headful mode:
await puppeteer.launch({
headless: false, // Set to false for debugging
// ... other options
});- puppeteer: Browser automation for screenshot capture
- pixelmatch: Pixel-level image comparison
- fs-extra: Enhanced file system operations
- commander: CLI framework
- chalk: Terminal colors and formatting
MIT License - feel free to use this in your projects!