snap_diff-capybara 2.0.0.beta3 → 2.0.0.beta4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +438 -0
  3. data/README.md +330 -0
  4. data/docs/UPGRADING.md +232 -34
  5. data/docs/architecture.md +9 -7
  6. data/docs/ci-integration.md +42 -11
  7. data/docs/configuration.md +176 -10
  8. data/docs/drivers.md +48 -5
  9. data/docs/framework-setup.md +10 -3
  10. data/docs/migration-guide.md +24 -13
  11. data/docs/reporters.md +70 -1
  12. data/docs/snapdiff.md +41 -8
  13. data/docs/thread_safety.md +77 -86
  14. data/lib/capybara/screenshot/diff/annotation_service.rb +1 -3
  15. data/lib/capybara/screenshot/diff/area_calculator.rb +1 -3
  16. data/lib/capybara/screenshot/diff/browser_helpers.rb +1 -3
  17. data/lib/capybara/screenshot/diff/config_legacy.rb +15 -60
  18. data/lib/capybara/screenshot/diff/difference.rb +1 -4
  19. data/lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb +3 -3
  20. data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +2 -3
  21. data/lib/capybara/screenshot/diff/drivers.rb +4 -5
  22. data/lib/capybara/screenshot/diff/image_compare.rb +11 -22
  23. data/lib/capybara/screenshot/diff/image_preprocessor.rb +1 -3
  24. data/lib/capybara/screenshot/diff/os.rb +4 -11
  25. data/lib/capybara/screenshot/diff/region.rb +2 -2
  26. data/lib/capybara/screenshot/diff/reporters/default.rb +4 -17
  27. data/lib/capybara/screenshot/diff/screenshot_matcher.rb +1 -3
  28. data/lib/capybara/screenshot/diff/screenshoter.rb +1 -3
  29. data/lib/capybara/screenshot/diff/stable_screenshoter.rb +1 -3
  30. data/lib/capybara/screenshot/diff/utils.rb +1 -3
  31. data/lib/capybara/screenshot/diff/vcs.rb +1 -3
  32. data/lib/capybara/screenshot/diff/version.rb +8 -13
  33. data/lib/capybara-screenshot-diff.rb +10 -1
  34. data/lib/capybara_screenshot_diff/attempts_reporter.rb +1 -3
  35. data/lib/capybara_screenshot_diff/dsl.rb +5 -0
  36. data/lib/capybara_screenshot_diff/error_with_filtered_backtrace.rb +1 -4
  37. data/lib/capybara_screenshot_diff/reporters/html.rb +1 -3
  38. data/lib/capybara_screenshot_diff/screenshot_namer.rb +1 -3
  39. data/lib/capybara_screenshot_diff/snap.rb +1 -3
  40. data/lib/capybara_screenshot_diff/snap_manager.rb +1 -3
  41. data/lib/capybara_screenshot_diff.rb +17 -21
  42. data/lib/snap_diff/browser_helpers.rb +26 -5
  43. data/lib/snap_diff/capture/viewport.rb +2 -5
  44. data/lib/snap_diff/comparison.rb +54 -3
  45. data/lib/snap_diff/comparison_result.rb +3 -1
  46. data/lib/snap_diff/config.rb +189 -93
  47. data/lib/snap_diff/deprecation.rb +89 -28
  48. data/lib/snap_diff/driver.rb +18 -0
  49. data/lib/snap_diff/drivers/vips_driver.rb +12 -6
  50. data/lib/snap_diff/drivers.rb +94 -12
  51. data/lib/snap_diff/dsl.rb +45 -47
  52. data/lib/snap_diff/integrations/cucumber.rb +1 -1
  53. data/lib/snap_diff/integrations/minitest.rb +45 -9
  54. data/lib/snap_diff/integrations/rspec.rb +11 -0
  55. data/lib/snap_diff/legacy_shims.rb +285 -27
  56. data/lib/snap_diff/removal.rb +159 -0
  57. data/lib/snap_diff/reporters/default.rb +86 -23
  58. data/lib/snap_diff/reporters/html.rb +29 -13
  59. data/lib/snap_diff/reporting.rb +329 -3
  60. data/lib/snap_diff/screenshot_assertion.rb +28 -23
  61. data/lib/snap_diff/screenshot_matcher.rb +121 -14
  62. data/lib/snap_diff/screenshot_namer.rb +1 -19
  63. data/lib/snap_diff/screenshoter.rb +5 -7
  64. data/lib/snap_diff/snap.rb +6 -1
  65. data/lib/snap_diff/snap_manager.rb +2 -3
  66. data/lib/snap_diff/stable_screenshoter.rb +2 -2
  67. data/lib/snap_diff/static.rb +1 -1
  68. data/lib/snap_diff/utils.rb +35 -17
  69. data/lib/snap_diff/vcs.rb +40 -7
  70. data/lib/snap_diff/version.rb +1 -1
  71. data/lib/snap_diff-capybara.rb +33 -3
  72. data/lib/snap_diff.rb +27 -37
  73. metadata +12 -10
  74. data/CODE_OF_CONDUCT.md +0 -129
  75. data/Rakefile +0 -65
  76. data/capybara-screenshot-diff.gemspec +0 -29
  77. data/docs/RELEASE_PREP.md +0 -44
  78. data/docs/docker-testing.md +0 -24
  79. data/gems.rb +0 -39
data/README.md ADDED
@@ -0,0 +1,330 @@
1
+ [![Gem Version](https://badge.fury.io/rb/capybara-screenshot-diff.svg)](https://rubygems.org/gems/capybara-screenshot-diff)
2
+ [![Gem Downloads](https://img.shields.io/gem/dt/capybara-screenshot-diff.svg)](https://rubygems.org/gems/capybara-screenshot-diff)
3
+ [![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)
4
+ [![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)
5
+
6
+ # Capybara::Screenshot::Diff
7
+
8
+ 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.
9
+
10
+ [![SnapDiff Web UI](docs/images/snap_diff_web_ui.png)](#web-ui-for-reviewing-screenshot-changes)
11
+
12
+ **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.
13
+
14
+ > **2.0 is the transitional release.** The gem's canonical namespace is now `SnapDiff`. Upgrading from 1.x is a version bump — every legacy `Capybara::Screenshot::Diff` / `CapybaraScreenshotDiff` name still resolves to the same object and keeps working. A legacy **config accessor**, an `include Capybara::Screenshot[::Diff]`, `Diff.default_options`, or a lazily shimmed legacy constant prints one migration notice per process (shimmed constants also warn once each). **The legacy integration require is not one of those doors** — `require "capybara_screenshot_diff/minitest"` plus `include CapybaraScreenshotDiff::Minitest::Assertions` is silent by design, because those names are eager aliases with no `const_missing` to hook. See [which names warn](docs/UPGRADING.md#deprecation-warnings). Silence the ones that do via `SnapDiff.silence_deprecations = true` or `SNAP_DIFF_SILENCE_DEPRECATIONS=1`.
15
+ >
16
+ > **2.1 removes what 2.0 warns about**: the legacy namespaces, the ChunkyPNG driver, `shift_distance_limit`, the `driver:` setting and the driver abstraction — libvips becomes the only backend. There is no 3.0. Writing new code? Start from [SnapDiff — the canonical API](docs/snapdiff.md), which uses canonical names only. Migrating an existing suite? See the [upgrade guide](docs/UPGRADING.md).
17
+ >
18
+ > **Two gem names, one gem — install `capybara-screenshot-diff`.** From 2.0.0 on, the identical content is also published as [`snap_diff-capybara`](https://rubygems.org/gems/snap_diff-capybara), the forward-looking name matching this repository. Do not reach for it yet: that name's only non-prerelease before 2.0.0 is a `0.0.1` placeholder containing a README and no Ruby files, so an unpinned `gem "snap_diff-capybara"` installs an empty gem and fails with `LoadError`. **Always pin the version**, and **install one name, never both** — with both in a Gemfile the gem raises `SnapDiff::DualInstallError` at require time.
19
+
20
+ ## Quick Start (5 minutes)
21
+
22
+ > 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).
23
+
24
+ ```ruby
25
+ # Gemfile
26
+ gem 'capybara-screenshot-diff', '2.0.0.beta4' # current 2.0 prerelease; 2.0.0 final is not out yet
27
+ gem 'ruby-vips' # The image backend. Needs libvips — see Installation below
28
+ ```
29
+
30
+ Pin the exact prerelease. Bundler never resolves a prerelease from a plain requirement, so
31
+ `'~> 2.0'` fails with `Could not find gem 'capybara-screenshot-diff (~> 2.0)'` until 2.0.0
32
+ ships. Once it does, `'~> 2.0'` is the pin to use.
33
+
34
+ The gem ships no image backend of its own. Add `ruby-vips` (recommended, and the only
35
+ backend from 2.1 on) or `chunky_png` (pure Ruby, no system library, removed in 2.1) — with
36
+ neither, comparisons raise `Wrong adapter nil. Available adapters: []`.
37
+
38
+ ```ruby
39
+ # test/test_helper.rb
40
+ require "snap_diff/integrations/minitest"
41
+ ```
42
+
43
+ ```ruby
44
+ # test/application_system_test_case.rb
45
+ require "test_helper"
46
+
47
+ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
48
+ driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
49
+
50
+ include SnapDiff::Minitest::Assertions
51
+ end
52
+ ```
53
+
54
+ ```ruby
55
+ # test/system/homepage_test.rb
56
+ require "application_system_test_case"
57
+
58
+ class HomepageTest < ApplicationSystemTestCase
59
+ test "homepage" do
60
+ visit "/"
61
+ assert_matches_screenshot "homepage"
62
+ end
63
+ end
64
+ ```
65
+
66
+ > **Pin the browser.** `driven_by` is not optional decoration in a pixel-diffing suite.
67
+ > Rails falls back to a *visible* browser at whatever size and pixel ratio the machine
68
+ > gives it: the same page that captures as **1400x1257** with the line above captures as
69
+ > **2800x1610** without it, and every comparison then fails with `Dimensions have changed`.
70
+ > Both `require` lines matter too — Rails does not autoload `test/`, so dropping either
71
+ > one raises `NameError: uninitialized constant`.
72
+
73
+ `SnapDiff::Minitest::Assertions` already includes `SnapDiff::DSL`, so no separate include is
74
+ needed. The legacy `require "capybara_screenshot_diff/minitest"` +
75
+ `include CapybaraScreenshotDiff::Minitest::Assertions` still work and resolve to these same
76
+ objects — 2.1 removes them, so new suites should start here. See
77
+ [SnapDiff — the canonical API](docs/snapdiff.md).
78
+
79
+ (`screenshot` still works as a shorthand, and is safe to override in your own helpers — the gem no longer calls it internally.)
80
+
81
+ Then run these steps in order:
82
+
83
+ ```bash
84
+ # Step 1: Save baselines (first run always passes)
85
+ bin/rails test:system
86
+
87
+ # Step 2: Commit baselines to git
88
+ git add doc/screenshots/
89
+ git commit -m "chore: add screenshot baselines"
90
+
91
+ # Step 3: Now comparisons work — change your UI and re-run
92
+ bin/rails test:system
93
+ ```
94
+
95
+ > **Run the task that actually runs system tests.** In a Rails app, `rake test`
96
+ > and `rails test` skip `test/system/` — you get `0 runs` and no baselines, which
97
+ > looks like a pass. Use `rails test:system` (or `rails test test/system`).
98
+ > Outside Rails, run whatever task loads your Capybara tests.
99
+
100
+ After Step 1, you'll see:
101
+ ```text
102
+ doc/screenshots/
103
+ homepage.png <- your baseline (commit this)
104
+ ```
105
+
106
+ Add diff artifacts to `.gitignore` — these are generated at runtime and should not be committed:
107
+ ```gitignore
108
+ # Screenshot diff artifacts (generated, not committed)
109
+ *.diff.png
110
+ *.base.png
111
+ *.diff.webp
112
+ *.base.webp
113
+ snap_diff_report.html
114
+ ```
115
+
116
+ If you skip Step 2 and push to CI, the build will fail — `fail_if_new` is `true` by default in CI.
117
+
118
+ For RSpec, Cucumber, or non-Rails setup, see [SnapDiff — the canonical API](docs/snapdiff.md#quick-start)
119
+ (or [Framework Setup](docs/framework-setup.md) for the same wiring in legacy names).
120
+
121
+ ### For Non-Rails Projects (Hugo, Jekyll, Static Sites)
122
+
123
+ ```ruby
124
+ require "snap_diff/static"
125
+ SnapDiff.serve("_site") # or "public", "build", "dist"
126
+ ```
127
+
128
+ Then commit baselines to git just like Rails. [Full setup](docs/ci-integration.md#non-rails-projects-hugo-jekyll-static-sites).
129
+
130
+ ## What Happens When a Screenshot Changes
131
+
132
+ The test fails with a clear message and generates diff files:
133
+
134
+ ```text
135
+ Screenshot does not match for 'homepage': ({"area_size":41520.0,"region":[8.0,8.0,1392.0,38.0]})
136
+ doc/screenshots/homepage.png
137
+ doc/screenshots/homepage.base.diff.png
138
+ doc/screenshots/homepage.diff.png
139
+ doc/screenshots/homepage.heatmap.diff.png
140
+ ```
141
+
142
+ Open `doc/screenshots/homepage.diff.png` to see exactly what changed. If the change is intentional, see [Accepting an intentional change](#accepting-an-intentional-change).
143
+
144
+ A failing run leaves five files behind — the rewritten baseline plus four artifacts:
145
+
146
+ | File | Description |
147
+ |------|-------------|
148
+ | `homepage.png` | Baseline path — **rewritten** with the new capture (`git status` shows it modified) |
149
+ | `homepage.base.png` | The committed baseline, checked out of `HEAD` for the comparison |
150
+ | `homepage.diff.png` | The new capture, with changed regions highlighted |
151
+ | `homepage.base.diff.png` | The old baseline, with the same regions highlighted |
152
+ | `homepage.heatmap.diff.png` | Heatmap of pixel differences |
153
+
154
+ Only `homepage.png` is committed; the `.gitignore` above keeps the other four out.
155
+
156
+ ## Accepting an intentional change
157
+
158
+ **Baselines are read from git, not from your working directory.** Every comparison runs
159
+ `git show HEAD:<path>` for the baseline, so a screenshot that is committed is the one you
160
+ are compared against — no matter what the file on disk says.
161
+
162
+ That makes the obvious move the wrong one: **deleting the baseline file does nothing.** The
163
+ gem fetches the committed copy from `HEAD` and the test fails exactly as before.
164
+
165
+ Accepting a change is therefore a **commit**, not a file operation. The run writes its new
166
+ capture to the baseline path, so `git status` shows the baseline as modified — review it and
167
+ commit it:
168
+
169
+ ```bash
170
+ git status # doc/screenshots/homepage.png is modified
171
+ git diff --stat doc/screenshots/
172
+
173
+ # Look at homepage.diff.png. If the change is what you wanted:
174
+ git add doc/screenshots/homepage.png
175
+ git commit -m "chore: update homepage baseline"
176
+
177
+ bin/rails test:system # now green — HEAD holds the new baseline
178
+ ```
179
+
180
+ > **Staging is not enough.** `git add` alone does not move `HEAD`, so a staged-but-uncommitted
181
+ > baseline is still compared against the old committed one. You cannot get a green local run
182
+ > until you commit. That is by design: the baseline under review in a pull request is exactly
183
+ > the baseline the suite uses.
184
+
185
+ Reviewing the change is what the pull request is for — the updated `.png` shows up as an image
186
+ diff next to the code that caused it.
187
+
188
+ ### Accepting many at once
189
+
190
+ One failure at a time is fine for one screenshot. After a redesign that changed forty, set the
191
+ **record mode** to `:all` and re-record them in a single run:
192
+
193
+ ```ruby
194
+ # test_helper.rb
195
+ SnapDiff.config.record = ENV["ACCEPT_SCREENSHOTS"] ? :all : :once
196
+ ```
197
+
198
+ ```bash
199
+ ACCEPT_SCREENSHOTS=1 bin/rails test:system
200
+ # [snap_diff] record: :all re-recorded 40 screenshots WITHOUT comparing: ...
201
+
202
+ git status # forty modified baselines, and nothing else
203
+ git add doc/screenshots/
204
+ git commit -m "chore: re-record baselines after the checkout redesign"
205
+ ```
206
+
207
+ `:all` writes every capture straight to its baseline path and compares nothing, so `git status`
208
+ is the review surface — look at the images before you commit. It **refuses to run under CI**,
209
+ where there would be nobody to look. The other modes are `:once` (the default) and `:none`
210
+ (strict — a missing baseline always fails); see
211
+ [Record modes](docs/configuration.md#record-modes--accepting-changes).
212
+
213
+ ## Web UI for Reviewing Screenshot Changes
214
+
215
+ Add one line to get an interactive dashboard for reviewing all screenshot differences:
216
+
217
+ ```ruby
218
+ # test/test_helper.rb
219
+ require 'capybara_screenshot_diff/reporters/html'
220
+ ```
221
+
222
+ After tests run, open `doc/screenshots/snap_diff_report.html`:
223
+
224
+ ![SnapDiff Web UI — annotated diff showing changed regions highlighted in red](docs/images/snap_diff_annotated.png)
225
+
226
+ See [Web UI & Custom Reporters](docs/reporters.md) for full feature details and [CI Integration](docs/ci-integration.md) for GitHub Actions setup.
227
+
228
+ ## Compare Any Two Images
229
+
230
+ Works without a browser — PDFs, generated images, CI artifacts:
231
+
232
+ ```ruby
233
+ result = Capybara::Screenshot::Diff.compare("baseline.png", "current.png")
234
+ result.different? # => true if visually different
235
+ result.quick_equal? # => true if byte-identical
236
+ ```
237
+
238
+ ## Next Steps
239
+
240
+ - **Crop to element:** `screenshot "form", crop: "#main-form"`
241
+ - **Ignore regions:** `screenshot "dashboard", skip_area: [".timestamp"]`
242
+ - **Disable animations:** `Capybara::Screenshot.disable_animations = true`
243
+ - **Set window size:** `Capybara::Screenshot.window_size = [1280, 1024]`
244
+
245
+ ## Handling Flaky Tests
246
+
247
+ Defaults work for most Rails apps — `blur_active_element`, `hide_caret`, and `fail_if_new` (in CI) are enabled automatically.
248
+
249
+ If screenshots differ between CI and local, set a comparison threshold:
250
+
251
+ ```ruby
252
+ Capybara::Screenshot::Diff.configure do |screenshot, diff|
253
+ screenshot.window_size = [1280, 1024] # consistent viewport
254
+ diff.perceptual_threshold = 2.0 # ignore anti-aliasing (VIPS only)
255
+ # or: diff.tolerance = 0.001 # percentage-based (default for VIPS)
256
+ end
257
+ ```
258
+
259
+ See [Choosing the Right Method](docs/configuration.md#choosing-the-right-color-comparison-method) for detailed comparison options.
260
+
261
+ ## FAQ
262
+
263
+ <details>
264
+ <summary><strong>The test passed on first run. Did it work?</strong></summary>
265
+
266
+ Yes. First run saves baselines and always passes. Run tests again to compare against committed baselines.
267
+ </details>
268
+
269
+ <details>
270
+ <summary><strong>How do I update baselines after intentional UI changes?</strong></summary>
271
+
272
+ **Not by deleting the file** — baselines are read from git (`git show HEAD:<path>`), so `rm` has no effect on what you are compared against. Commit the new capture instead: `git add doc/screenshots/homepage.png && git commit`. See [Accepting an intentional change](#accepting-an-intentional-change).
273
+ </details>
274
+
275
+ <details>
276
+ <summary><strong>CSS animations make my screenshots flaky</strong></summary>
277
+
278
+ 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.
279
+ </details>
280
+
281
+ <details>
282
+ <summary><strong>CI screenshots differ from local</strong></summary>
283
+
284
+ Set `window_size` for consistent dimensions and use `perceptual_threshold: 2.0` to ignore anti-aliasing differences across environments.
285
+ </details>
286
+
287
+ <details>
288
+ <summary><strong>Will this slow down my tests?</strong></summary>
289
+
290
+ Comparisons add ~50ms per image with VIPS. If you add `chunky_png` to your Gemfile instead, it is used as a pure-Ruby fallback (slower, no system dependency, and removed in 2.1). `stability_time_limit` adds wait time — keep it low (0.1-0.5s) or use `disable_animations` instead.
291
+ </details>
292
+
293
+ <details>
294
+ <summary><strong>Debug mode</strong></summary>
295
+
296
+ You do not need a flag to keep the diff images — a failing run leaves `.diff.png`,
297
+ `.base.diff.png`, `.heatmap.diff.png` and `.base.png` on disk and nothing in the gem
298
+ deletes them (`SnapManager#cleanup!` is this repository's own test-harness call, not
299
+ something your suite runs).
300
+
301
+ `DEBUG=1` does one thing: it makes the HTML reporter print why it skipped an assertion
302
+ instead of failing quietly — useful when `snap_diff_report.html` is missing entries.
303
+ </details>
304
+
305
+ ## Installation
306
+
307
+ **Requirements:** Ruby 3.2+, Capybara 2–3. Rails 7.1+ for Rails integration; non-Rails projects supported via `SnapDiff.serve()`. For the `:vips` driver (recommended, and the only backend from 2.1 on): [libvips 8.9+](https://libvips.github.io/libvips/install.html). On macOS: `brew install vips`. On Ubuntu: `apt-get install libvips-dev`.
308
+
309
+ ## Docs
310
+
311
+ - [SnapDiff — the canonical API](docs/snapdiff.md) — setup, config, object map, custom drivers & reporters, canonical names only
312
+ - [Upgrading](docs/UPGRADING.md) — 1.x → 2.0, every renamed constant, which names warn, what 2.1 removes, rollback
313
+ - [Framework Setup](docs/framework-setup.md) — Minitest, RSpec, Cucumber
314
+ - [CI & Non-Rails Integration](docs/ci-integration.md) — GitHub Actions, reusable action, static sites, baseline updates
315
+ - [Configuration Reference](docs/configuration.md) — all options explained
316
+ - [Image Processing Drivers](docs/drivers.md) — VIPS, ChunkyPNG, perceptual threshold
317
+ - [Screenshot Organization](docs/organization.md) — groups, sections, cropping, multi-browser
318
+ - [Web UI & Custom Reporters](docs/reporters.md) — interactive report, custom reporters
319
+
320
+ ## Development
321
+
322
+ After checking out the repo, run `bin/setup` then `rake test`. See [Docker Testing](https://github.com/snap-diff/snap_diff-capybara/blob/master/docs/docker-testing.md) for reproducible CI-matching test runs.
323
+
324
+ ## Contributing
325
+
326
+ See [CONTRIBUTING.md](https://github.com/snap-diff/snap_diff-capybara/blob/master/CONTRIBUTING.md)
327
+
328
+ ## License
329
+
330
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).