{"id":13878398,"url":"https://github.com/snap-diff/snap_diff-capybara","last_synced_at":"2026-06-11T16:01:00.150Z","repository":{"id":37405878,"uuid":"54958798","full_name":"snap-diff/snap_diff-capybara","owner":"snap-diff","description":"Visual regression testing for Rails — screenshot diffs in your Capybara tests, baselines in git, no SaaS needed","archived":false,"fork":false,"pushed_at":"2026-05-20T20:06:05.000Z","size":4971,"stargazers_count":64,"open_issues_count":1,"forks_count":16,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-06-10T00:04:59.044Z","etag":null,"topics":["capybara","rails","ruby","screenshot-testing","visual-regression-testing"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/snap-diff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-03-29T08:26:39.000Z","updated_at":"2026-06-04T16:29:25.000Z","dependencies_parsed_at":"2024-01-02T23:52:41.449Z","dependency_job_id":"962ea3d5-318a-449e-ac28-53294a59b53b","html_url":"https://github.com/snap-diff/snap_diff-capybara","commit_stats":{"total_commits":265,"total_committers":10,"mean_commits":26.5,"dds":0.4037735849056604,"last_synced_commit":"c637b6d48253a9f26e80f8e584f8e9a92dc53344"},"previous_names":["capybara-screenshot-diff/capybara-screenshot-diff"],"tags_count":71,"template":false,"template_full_name":null,"purl":"pkg:github/snap-diff/snap_diff-capybara","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snap-diff%2Fsnap_diff-capybara","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snap-diff%2Fsnap_diff-capybara/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snap-diff%2Fsnap_diff-capybara/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snap-diff%2Fsnap_diff-capybara/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snap-diff","download_url":"https://codeload.github.com/snap-diff/snap_diff-capybara/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snap-diff%2Fsnap_diff-capybara/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34206492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["capybara","rails","ruby","screenshot-testing","visual-regression-testing"],"created_at":"2024-08-06T08:01:48.431Z","updated_at":"2026-06-11T16:01:00.144Z","avatar_url":"https://github.com/snap-diff.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"[![Gem Version](https://badge.fury.io/rb/capybara-screenshot-diff.svg)](https://rubygems.org/gems/capybara-screenshot-diff)\n[![Gem Downloads](https://img.shields.io/gem/dt/capybara-screenshot-diff.svg)](https://rubygems.org/gems/capybara-screenshot-diff)\n[![Test](https://github.com/snap-diff/snap_diff-capybara/actions/workflows/test.yml/badge.svg)](https://github.com/snap-diff/snap_diff-capybara/actions/workflows/test.yml)\n[![DeepWiki](https://img.shields.io/badge/DeepWiki-snap--diff%2Fsnap__diff--capybara-blue.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTEyIDJhMTAgMTAgMCAxIDAgMCAyMCAxMCAxMCAwIDAgMCAwLTIweiIvPjxwYXRoIGQ9Ik0xMiA2djEyIi8+PHBhdGggZD0iTTYgMTJoMTIiLz48L3N2Zz4=)](https://deepwiki.com/snap-diff/snap_diff-capybara)\n\n# Capybara::Screenshot::Diff\n\nStop 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.\n\n[![SnapDiff Web UI](docs/images/snap_diff_web_ui.png)](#web-ui-for-reviewing-screenshot-changes)\n\n**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.\n\n## Quick Start (5 minutes)\n\n\u003e 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).\n\n```ruby\n# Gemfile\ngem 'capybara-screenshot-diff'\ngem 'ruby-vips'  # Optional: 10x faster comparisons\n```\n\n```ruby\n# test/test_helper.rb\nrequire 'capybara_screenshot_diff/minitest'\n```\n\n```ruby\n# test/application_system_test_case.rb\nclass ApplicationSystemTestCase \u003c ActionDispatch::SystemTestCase\n  include CapybaraScreenshotDiff::Minitest::Assertions\nend\n```\n\n```ruby\n# test/system/homepage_test.rb\nclass HomepageTest \u003c ApplicationSystemTestCase\n  test \"homepage\" do\n    visit \"/\"\n    screenshot \"homepage\"\n  end\nend\n```\n\nThen run these steps in order:\n\n```bash\n# Step 1: Save baselines (first run always passes)\nbundle exec rake test\n\n# Step 2: Commit baselines to git\ngit add doc/screenshots/\ngit commit -m \"chore: add screenshot baselines\"\n\n# Step 3: Now comparisons work — change your UI and re-run\nbundle exec rake test\n```\n\nAfter Step 1, you'll see:\n```text\ndoc/screenshots/\n  homepage.png          \u003c- your baseline (commit this)\n```\n\nAdd diff artifacts to `.gitignore` — these are generated at runtime and should not be committed:\n```gitignore\n# Screenshot diff artifacts (generated, not committed)\n*.diff.png\n*.base.png\n*.diff.webp\n*.base.webp\nsnap_diff_report.html\n```\n\nIf you skip Step 2 and push to CI, the build will fail — `fail_if_new` is `true` by default in CI.\n\nFor RSpec, Cucumber, or non-Rails setup, see [Framework Setup](docs/framework-setup.md).\n\n### For Non-Rails Projects (Hugo, Jekyll, Static Sites)\n\n```ruby\nrequire 'capybara_screenshot_diff/static'\nCapybaraScreenshotDiff.serve(\"_site\")  # or \"public\", \"build\", \"dist\"\n```\n\nThen commit baselines to git just like Rails. [Full setup](docs/ci-integration.md#non-rails-projects-hugo-jekyll-static-sites).\n\n## What Happens When a Screenshot Changes\n\nThe test fails with a clear message and generates diff files:\n\n```text\nScreenshot does not match for 'homepage':\n({\"area_size\":1250,\"region\":[0,19,199,83],\"max_color_distance\":42.5})\n```\n\nOpen `doc/screenshots/homepage.diff.png` to see exactly what changed. If the change is intentional, delete the baseline and re-run to update it.\n\n| File | Description |\n|------|-------------|\n| `homepage.png` | Committed baseline |\n| `homepage.diff.png` | Visual diff with changes highlighted in red |\n| `homepage.heatmap.diff.png` | Heatmap of pixel differences |\n\n## Web UI for Reviewing Screenshot Changes\n\nAdd one line to get an interactive dashboard for reviewing all screenshot differences:\n\n```ruby\n# test/test_helper.rb\nrequire 'capybara_screenshot_diff/reporters/html'\n```\n\nAfter tests run, open `doc/screenshots/snap_diff_report.html`:\n\n![SnapDiff Web UI — annotated diff showing changed regions highlighted in red](docs/images/snap_diff_annotated.png)\n\nSee [Web UI \u0026 Custom Reporters](docs/reporters.md) for full feature details and [CI Integration](docs/ci-integration.md) for GitHub Actions setup.\n\n## Compare Any Two Images\n\nWorks without a browser — PDFs, generated images, CI artifacts:\n\n```ruby\nresult = Capybara::Screenshot::Diff.compare(\"baseline.png\", \"current.png\")\nresult.different?    # =\u003e true if visually different\nresult.quick_equal?  # =\u003e true if byte-identical\n```\n\n## Next Steps\n\n- **Crop to element:** `screenshot \"form\", crop: \"#main-form\"`\n- **Ignore regions:** `screenshot \"dashboard\", skip_area: [\".timestamp\"]`\n- **Disable animations:** `Capybara::Screenshot.disable_animations = true`\n- **Set window size:** `Capybara::Screenshot.window_size = [1280, 1024]`\n\n## Handling Flaky Tests\n\nDefaults work for most Rails apps — `blur_active_element`, `hide_caret`, and `fail_if_new` (in CI) are enabled automatically.\n\nIf screenshots differ between CI and local, set a comparison threshold:\n\n```ruby\nCapybara::Screenshot::Diff.configure do |screenshot, diff|\n  screenshot.window_size = [1280, 1024]        # consistent viewport\n  diff.perceptual_threshold = 2.0              # ignore anti-aliasing (VIPS only)\n  # or: diff.tolerance = 0.001                 # percentage-based (default for VIPS)\nend\n```\n\nSee [Choosing the Right Method](docs/configuration.md#choosing-the-right-color-comparison-method) for detailed comparison options.\n\n## FAQ\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eThe test passed on first run. Did it work?\u003c/strong\u003e\u003c/summary\u003e\n\nYes. First run saves baselines and always passes. Run tests again to compare against committed baselines.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eHow do I update baselines after intentional UI changes?\u003c/strong\u003e\u003c/summary\u003e\n\nDelete the baseline file and re-run tests: `rm doc/screenshots/homepage.png \u0026\u0026 bundle exec rake test`. Or update all: `rm -rf doc/screenshots/ \u0026\u0026 bundle exec rake test`.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCSS animations make my screenshots flaky\u003c/strong\u003e\u003c/summary\u003e\n\nEnable `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.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCI screenshots differ from local\u003c/strong\u003e\u003c/summary\u003e\n\nSet `window_size` for consistent dimensions and use `perceptual_threshold: 2.0` to ignore anti-aliasing differences across environments.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eWill this slow down my tests?\u003c/strong\u003e\u003c/summary\u003e\n\nComparisons 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.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDebug mode\u003c/strong\u003e\u003c/summary\u003e\n\n`DEBUG=1 bundle exec rake test` keeps `.diff.png` files for inspection.\n\u003c/details\u003e\n\n## Installation\n\n**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`.\n\n## Docs\n\n- [Framework Setup](docs/framework-setup.md) — Minitest, RSpec, Cucumber\n- [CI \u0026 Non-Rails Integration](docs/ci-integration.md) — GitHub Actions, reusable action, static sites, baseline updates\n- [Configuration Reference](docs/configuration.md) — all options explained\n- [Image Processing Drivers](docs/drivers.md) — VIPS, ChunkyPNG, perceptual threshold\n- [Screenshot Organization](docs/organization.md) — groups, sections, cropping, multi-browser\n- [Web UI \u0026 Custom Reporters](docs/reporters.md) — interactive report, custom reporters\n\n## Development\n\nAfter checking out the repo, run `bin/setup` then `rake test`. See [Docker Testing](docs/docker-testing.md) for reproducible CI-matching test runs.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnap-diff%2Fsnap_diff-capybara","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnap-diff%2Fsnap_diff-capybara","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnap-diff%2Fsnap_diff-capybara/lists"}