Skip to content

snap-diff/snap_diff-capybara

Repository files navigation

Gem Version Gem Downloads Test DeepWiki

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.

SnapDiff Web UI

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.

# Gemfile
gem 'capybara-screenshot-diff'
gem 'ruby-vips'  # Optional: 10x faster comparisons
# test/test_helper.rb
require 'capybara_screenshot_diff/minitest'
# test/application_system_test_case.rb
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  include CapybaraScreenshotDiff::Minitest::Assertions
end
# test/system/homepage_test.rb
class HomepageTest < ApplicationSystemTestCase
  test "homepage" do
    visit "/"
    screenshot "homepage"
  end
end

Then run these steps in order:

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

doc/screenshots/
  homepage.png          <- your baseline (commit this)

Add diff artifacts to .gitignore — these are generated at runtime and should not be committed:

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

For Non-Rails Projects (Hugo, Jekyll, Static Sites)

require 'capybara_screenshot_diff/static'
CapybaraScreenshotDiff.serve("_site")  # or "public", "build", "dist"

Then commit baselines to git just like Rails. Full setup.

What Happens When a Screenshot Changes

The test fails with a clear message and generates diff files:

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:

# test/test_helper.rb
require 'capybara_screenshot_diff/reporters/html'

After tests run, open doc/screenshots/snap_diff_report.html:

SnapDiff Web UI — annotated diff showing changed regions highlighted in red

Review all visual changes in one place — no need to hunt through .diff.png files. 4 view modes (both/base/new/heatmap), per-image zoom, annotation toggle, keyboard navigation, and search.

In GitHub Actions, one step uploads the report, posts a PR comment with the link, and adds a job summary:

- name: Upload screenshot report
  if: failure()
  uses: snap-diff/snap_diff-capybara/.github/actions/upload-screenshots@master
  with:
    name: screenshots
    pr-comment: 'true'

See CI Integration for full setup including Ruby + libvips action and baseline update workflow.

Compare Any Two Images

Works without a browser — PDFs, generated images, CI artifacts:

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:

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 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+. On macOS: brew install vips. On Ubuntu: apt-get install libvips-dev.

Docs

Development

After checking out the repo, run bin/setup then rake test. See Docker Testing for reproducible CI-matching test runs.

Contributing

See CONTRIBUTING.md

License

The gem is available as open source under the terms of the MIT License.

About

Visual regression testing for Rails — screenshot diffs in your Capybara tests, baselines in git, no SaaS needed

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages