https://github.com/snap-diff/snap_diff-capybara
Visual regression testing for Rails — screenshot diffs in your Capybara tests, baselines in git, no SaaS needed
https://github.com/snap-diff/snap_diff-capybara
capybara rails ruby screenshot-testing visual-regression-testing
Last synced: 8 days ago
JSON representation
Visual regression testing for Rails — screenshot diffs in your Capybara tests, baselines in git, no SaaS needed
- Host: GitHub
- URL: https://github.com/snap-diff/snap_diff-capybara
- Owner: snap-diff
- License: mit
- Created: 2016-03-29T08:26:39.000Z (about 10 years ago)
- Default Branch: master
- Last Pushed: 2026-05-20T20:06:05.000Z (about 1 month ago)
- Last Synced: 2026-06-10T00:04:59.044Z (10 days ago)
- Topics: capybara, rails, ruby, screenshot-testing, visual-regression-testing
- Language: Ruby
- Homepage:
- Size: 4.74 MB
- Stars: 64
- Watchers: 5
- Forks: 16
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
Awesome Lists containing this project
README
[](https://rubygems.org/gems/capybara-screenshot-diff)
[](https://rubygems.org/gems/capybara-screenshot-diff)
[](https://github.com/snap-diff/snap_diff-capybara/actions/workflows/test.yml)
[](https://deepwiki.com/snap-diff/snap_diff-capybara)
# Capybara::Screenshot::Diff
Stop shipping UI bugs. Take screenshots in your Capybara tests, commit baselines to git, and let CI catch visual regressions in pull requests — no cloud service, no subscription, runs entirely in your test suite.
[](#web-ui-for-reviewing-screenshot-changes)
**Why this gem?** Baselines live in git — review UI changes in pull requests like you review code. Runs offline, works in CI, zero vendor lock-in. Unlike Percy/Chromatic (paid SaaS), nothing to sign up for. Unlike BackstopJS, no Node required.
## Quick Start (5 minutes)
> Already using Capybara for system tests? Add the gem and you're ready. New to system tests? See [Rails System Testing guide](https://guides.rubyonrails.org/testing.html#system-testing).
```ruby
# Gemfile
gem 'capybara-screenshot-diff'
gem 'ruby-vips' # Optional: 10x faster comparisons
```
```ruby
# test/test_helper.rb
require 'capybara_screenshot_diff/minitest'
```
```ruby
# test/application_system_test_case.rb
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
include CapybaraScreenshotDiff::Minitest::Assertions
end
```
```ruby
# test/system/homepage_test.rb
class HomepageTest < ApplicationSystemTestCase
test "homepage" do
visit "/"
screenshot "homepage"
end
end
```
Then run these steps in order:
```bash
# Step 1: Save baselines (first run always passes)
bundle exec rake test
# Step 2: Commit baselines to git
git add doc/screenshots/
git commit -m "chore: add screenshot baselines"
# Step 3: Now comparisons work — change your UI and re-run
bundle exec rake test
```
After Step 1, you'll see:
```text
doc/screenshots/
homepage.png <- your baseline (commit this)
```
Add diff artifacts to `.gitignore` — these are generated at runtime and should not be committed:
```gitignore
# Screenshot diff artifacts (generated, not committed)
*.diff.png
*.base.png
*.diff.webp
*.base.webp
snap_diff_report.html
```
If you skip Step 2 and push to CI, the build will fail — `fail_if_new` is `true` by default in CI.
For RSpec, Cucumber, or non-Rails setup, see [Framework Setup](docs/framework-setup.md).
### For Non-Rails Projects (Hugo, Jekyll, Static Sites)
```ruby
require 'capybara_screenshot_diff/static'
CapybaraScreenshotDiff.serve("_site") # or "public", "build", "dist"
```
Then commit baselines to git just like Rails. [Full setup](docs/ci-integration.md#non-rails-projects-hugo-jekyll-static-sites).
## What Happens When a Screenshot Changes
The test fails with a clear message and generates diff files:
```text
Screenshot does not match for 'homepage':
({"area_size":1250,"region":[0,19,199,83],"max_color_distance":42.5})
```
Open `doc/screenshots/homepage.diff.png` to see exactly what changed. If the change is intentional, delete the baseline and re-run to update it.
| File | Description |
|------|-------------|
| `homepage.png` | Committed baseline |
| `homepage.diff.png` | Visual diff with changes highlighted in red |
| `homepage.heatmap.diff.png` | Heatmap of pixel differences |
## Web UI for Reviewing Screenshot Changes
Add one line to get an interactive dashboard for reviewing all screenshot differences:
```ruby
# test/test_helper.rb
require 'capybara_screenshot_diff/reporters/html'
```
After tests run, open `doc/screenshots/snap_diff_report.html`:

See [Web UI & Custom Reporters](docs/reporters.md) for full feature details and [CI Integration](docs/ci-integration.md) for GitHub Actions setup.
## Compare Any Two Images
Works without a browser — PDFs, generated images, CI artifacts:
```ruby
result = Capybara::Screenshot::Diff.compare("baseline.png", "current.png")
result.different? # => true if visually different
result.quick_equal? # => true if byte-identical
```
## Next Steps
- **Crop to element:** `screenshot "form", crop: "#main-form"`
- **Ignore regions:** `screenshot "dashboard", skip_area: [".timestamp"]`
- **Disable animations:** `Capybara::Screenshot.disable_animations = true`
- **Set window size:** `Capybara::Screenshot.window_size = [1280, 1024]`
## Handling Flaky Tests
Defaults work for most Rails apps — `blur_active_element`, `hide_caret`, and `fail_if_new` (in CI) are enabled automatically.
If screenshots differ between CI and local, set a comparison threshold:
```ruby
Capybara::Screenshot::Diff.configure do |screenshot, diff|
screenshot.window_size = [1280, 1024] # consistent viewport
diff.perceptual_threshold = 2.0 # ignore anti-aliasing (VIPS only)
# or: diff.tolerance = 0.001 # percentage-based (default for VIPS)
end
```
See [Choosing the Right Method](docs/configuration.md#choosing-the-right-color-comparison-method) for detailed comparison options.
## FAQ
The test passed on first run. Did it work?
Yes. First run saves baselines and always passes. Run tests again to compare against committed baselines.
How do I update baselines after intentional UI changes?
Delete the baseline file and re-run tests: `rm doc/screenshots/homepage.png && bundle exec rake test`. Or update all: `rm -rf doc/screenshots/ && bundle exec rake test`.
CSS animations make my screenshots flaky
Enable `Capybara::Screenshot.disable_animations = true` to freeze CSS animations/transitions before each capture. Or use `stability_time_limit: 1` to wait for animations to finish.
CI screenshots differ from local
Set `window_size` for consistent dimensions and use `perceptual_threshold: 2.0` to ignore anti-aliasing differences across environments.
Will this slow down my tests?
Comparisons add ~50ms per image with VIPS. Without `ruby-vips`, ChunkyPNG is used (slower but no system dependency). `stability_time_limit` adds wait time — keep it low (0.1-0.5s) or use `disable_animations` instead.
Debug mode
`DEBUG=1 bundle exec rake test` keeps `.diff.png` files for inspection.
## Installation
**Requirements:** Ruby 3.2+. Rails 7.1+ for Rails integration; non-Rails projects supported via `CapybaraScreenshotDiff.serve()`. For the `:vips` driver: [libvips 8.9+](https://libvips.github.io/libvips/install.html). On macOS: `brew install vips`. On Ubuntu: `apt-get install libvips-dev`.
## Docs
- [Framework Setup](docs/framework-setup.md) — Minitest, RSpec, Cucumber
- [CI & Non-Rails Integration](docs/ci-integration.md) — GitHub Actions, reusable action, static sites, baseline updates
- [Configuration Reference](docs/configuration.md) — all options explained
- [Image Processing Drivers](docs/drivers.md) — VIPS, ChunkyPNG, perceptual threshold
- [Screenshot Organization](docs/organization.md) — groups, sections, cropping, multi-browser
- [Web UI & Custom Reporters](docs/reporters.md) — interactive report, custom reporters
## Development
After checking out the repo, run `bin/setup` then `rake test`. See [Docker Testing](docs/docker-testing.md) for reproducible CI-matching test runs.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).