snap_diff-capybara 2.0.0.beta1 → 2.0.0.beta2

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -0
  3. data/docs/UPGRADING.md +19 -4
  4. data/docs/architecture.md +38 -22
  5. data/docs/ci-integration.md +13 -3
  6. data/docs/configuration.md +31 -2
  7. data/docs/drivers.md +6 -0
  8. data/docs/framework-setup.md +21 -3
  9. data/docs/reporters.md +20 -5
  10. data/docs/snapdiff.md +326 -0
  11. data/docs/thread_safety.md +4 -3
  12. data/lib/capybara/screenshot/diff/config_legacy.rb +26 -72
  13. data/lib/capybara/screenshot/diff/image_compare.rb +5 -2
  14. data/lib/capybara/screenshot/diff/region.rb +3 -105
  15. data/lib/capybara/screenshot/diff/reporters/default.rb +4 -106
  16. data/lib/capybara_screenshot_diff/screenshot_assertion.rb +12 -24
  17. data/lib/capybara_screenshot_diff.rb +10 -4
  18. data/lib/snap_diff/area_calculator.rb +1 -3
  19. data/lib/snap_diff/browser_helpers.rb +1 -3
  20. data/lib/snap_diff/capture/viewport.rb +6 -7
  21. data/lib/snap_diff/comparison.rb +15 -28
  22. data/lib/snap_diff/config.rb +151 -29
  23. data/lib/snap_diff/deprecation.rb +26 -8
  24. data/lib/snap_diff/drivers.rb +20 -0
  25. data/lib/snap_diff/dsl.rb +12 -12
  26. data/lib/snap_diff/errors.rb +19 -0
  27. data/lib/snap_diff/integrations/cucumber.rb +5 -4
  28. data/lib/snap_diff/integrations/minitest.rb +11 -12
  29. data/lib/snap_diff/integrations/rspec.rb +7 -6
  30. data/lib/snap_diff/legacy_shims.rb +18 -0
  31. data/lib/snap_diff/region.rb +117 -0
  32. data/lib/snap_diff/reporters/default.rb +107 -0
  33. data/lib/snap_diff/reporters/html.rb +7 -9
  34. data/lib/snap_diff/reporting.rb +13 -4
  35. data/lib/snap_diff/screenshot_assertion.rb +37 -4
  36. data/lib/snap_diff/screenshot_matcher.rb +4 -4
  37. data/lib/snap_diff/screenshoter.rb +1 -1
  38. data/lib/snap_diff/snap_manager.rb +1 -2
  39. data/lib/snap_diff/stable_screenshoter.rb +2 -2
  40. data/lib/snap_diff/utils.rb +5 -3
  41. data/lib/snap_diff/version.rb +1 -1
  42. data/lib/snap_diff.rb +44 -15
  43. metadata +5 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a063da3ec86978a0e66baaa0c64692c40f18db15ce66b40cab390df9a90be5a1
4
- data.tar.gz: c34b6fe46a10353ed94d738832cd9dafca06ef0f7a53b2c678408010198f58d2
3
+ metadata.gz: 480337577271341982e3f8eef57cf123003092ba90833e4b4a497676920c0466
4
+ data.tar.gz: e844a383454976b32c46059e4593dd0c472133d22eac3e1d531b6bca35935f6e
5
5
  SHA512:
6
- metadata.gz: '0828945cb79fbf911727deeac0b4cf868f34b5787c37720bc216a6d893115a2d9486a43284cf3f3467834951d1ae438f969a7ea5e1dcdd8ae387fb2cf9f263b9'
7
- data.tar.gz: 3fc96895702aac83fa636bf8cfd1ac73953b4049b2629104ccbde592af150f3829c3eda7e73e8912b0342793cbf3e45d07056ffffb68c4f3b5594758406cd932
6
+ metadata.gz: b44e77a9e696cd8f326655ba6bd19d5b4275f7f2b86ea0961c913dc30d1ecb6eb0806fa89340359357049bf70c2c015ccaf4d22fc9f6d733c84788db358435f4
7
+ data.tar.gz: 322a1b64abd4bc2234dea9f6ffcda02f7dac5e9e09c640f1f6decc588b0715953add332a08a61e685bec944358b80b999f77a17b5524663e6c107f771ad7a2fb
data/CHANGELOG.md CHANGED
@@ -5,6 +5,62 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [v2.0.0.beta2] - 2026-08-23
9
+
10
+ Third prerelease of the 2.0 opt-in experiment. This one finishes the namespace
11
+ move: `SnapDiff` no longer depends on the namespaces it deprecates. Legacy names
12
+ keep working exactly as before — see the v2.0.0.alpha1 notes below for the
13
+ opt-in and silencing basics, and [docs/snapdiff.md](docs/snapdiff.md) for the
14
+ canonical API.
15
+
16
+ ### Changed
17
+ - **Everything canonical now lives in `SnapDiff`** — configuration storage
18
+ (`SnapDiff::Config`, one storage behind every settings surface), error classes
19
+ (`SnapDiff::Error`, `ExpectationNotMet`, `UnstableImage`,
20
+ `WindowSizeMismatchError`), `SnapDiff::Region`, `SnapDiff::Reporters::Default`,
21
+ the driver registry (`SnapDiff::Drivers.loaded`/`.available`), the per-test
22
+ session (`SnapDiff.session`), and reporter registration
23
+ (`SnapDiff::Reporting.register`, mutex-guarded). Old constants remain
24
+ same-object aliases; `rescue`, `is_a?`, and `defined?` on them are unchanged
25
+ ([#224](https://github.com/snap-diff/snap_diff-capybara/pull/224)–[#230](https://github.com/snap-diff/snap_diff-capybara/pull/230))
26
+ - **Error class names in failure output** now print as `SnapDiff::…` (the class
27
+ objects are identical, so `rescue CapybaraScreenshotDiff::ExpectationNotMet`
28
+ still catches them — only the printed name differs). CI jobs that
29
+ string-match on the old class name in output need updating.
30
+ - The images-holder struct is now `SnapDiff::Comparison::Images`, ending the
31
+ two-classes-one-name collision with the comparator
32
+ ([#227](https://github.com/snap-diff/snap_diff-capybara/pull/227))
33
+
34
+ ### Added
35
+ - **Deprecation warnings now name your call site** — `(called from
36
+ your_file.rb:42)`, so migration is warning-driven instead of grep-driven
37
+ ([#222](https://github.com/snap-diff/snap_diff-capybara/pull/222))
38
+ - **Dual-install guard** — installing both `capybara-screenshot-diff` and
39
+ `snap_diff-capybara` now raises a clear error instead of silently loading
40
+ files from whichever gem activated first
41
+ ([#222](https://github.com/snap-diff/snap_diff-capybara/pull/222))
42
+ - **[docs/snapdiff.md](docs/snapdiff.md)** — the SnapDiff-native guide: quick
43
+ start for all four integrations, configuration, custom drivers and reporters,
44
+ standalone comparison ([#231](https://github.com/snap-diff/snap_diff-capybara/pull/231))
45
+
46
+ ### Removed
47
+ - The unused `anchor:` keyword on the internal viewport seam; v3's
48
+ scroll-preservation work will design its real contract
49
+ ([#229](https://github.com/snap-diff/snap_diff-capybara/pull/229))
50
+
51
+ ### Internal
52
+ - A test now mechanically enforces that the legacy namespace trees contain only
53
+ requires, aliases, and one-line forwarders — no real logic — so removing them
54
+ in 3.0 is a deletion, not a refactor
55
+ ([#229](https://github.com/snap-diff/snap_diff-capybara/pull/229),
56
+ [#230](https://github.com/snap-diff/snap_diff-capybara/pull/230))
57
+ - Release workflow is idempotent on re-run; config default-eval timing is
58
+ pinned by guards across every entry point
59
+ ([#222](https://github.com/snap-diff/snap_diff-capybara/pull/222),
60
+ [#223](https://github.com/snap-diff/snap_diff-capybara/pull/223))
61
+
62
+ ---
63
+
8
64
  ## [v2.0.0.beta1] - 2026-08-22
9
65
 
10
66
  Second prerelease of the 2.0 opt-in experiment (see the v2.0.0.alpha1 notes
data/docs/UPGRADING.md CHANGED
@@ -6,10 +6,14 @@
6
6
 
7
7
  Version 2.0 introduces a new canonical namespace (`SnapDiff`) for cleaner, more discoverable code. The public DSL remains unchanged — your existing `screenshot` and `assert_matches_screenshot` calls work without modification. This guide covers the optional migration path for settings and the new namespace.
8
8
 
9
- **Status:** `2.0.0.alpha1` is an opt-in prerelease. RubyGems never installs prereleases by default resolution — normal `bundle update` keeps you on the 1.x line. The final 2.0.0 ships only after adopter feedback; please report anything surprising on [#166](https://github.com/snap-diff/snap_diff-capybara/issues/166).
9
+ **Status:** `2.0.0.beta2` is an opt-in prerelease. RubyGems never installs prereleases by default resolution — normal `bundle update` keeps you on the 1.x line. The final 2.0.0 ships only after adopter feedback; please report anything surprising on [#166](https://github.com/snap-diff/snap_diff-capybara/issues/166).
10
10
 
11
11
  **Estimated upgrade time:** 5–15 minutes (most users need only the Gemfile pin)
12
12
 
13
+ **Writing new code rather than migrating?** Skip this guide and read
14
+ [SnapDiff — the canonical API](snapdiff.md): the same setup, configuration, and extension points
15
+ with canonical names only, no legacy shapes to unlearn.
16
+
13
17
  **Breaking changes:** None for the DSL; deprecation warnings if you reference legacy constants (suppressible), plus two known alpha caveats (see below)
14
18
 
15
19
  ---
@@ -18,7 +22,7 @@ Version 2.0 introduces a new canonical namespace (`SnapDiff`) for cleaner, more
18
22
 
19
23
  ```ruby
20
24
  # In your Gemfile — the exact prerelease version is required to opt in
21
- gem "capybara-screenshot-diff", "2.0.0.alpha1"
25
+ gem "capybara-screenshot-diff", "2.0.0.beta2" # or the latest 2.0.0 prerelease
22
26
  ```
23
27
 
24
28
  ```bash
@@ -43,6 +47,17 @@ The implementation now lives in `lib/snap_diff/` under the `SnapDiff` namespace.
43
47
  | `Capybara::Screenshot::Diff::Drivers::BaseDriver` | `SnapDiff::Driver` (now a mixin — see below) |
44
48
  | `CapybaraScreenshotDiff::SnapManager` / `::Snap` | `SnapDiff::SnapManager` / `SnapDiff::Snap` |
45
49
  | `CapybaraScreenshotDiff::RED_RGBA` / `::ORANGE_RGBA` | `SnapDiff::RED_RGBA` / `SnapDiff::ORANGE_RGBA` |
50
+ | `CapybaraScreenshotDiff::Minitest::Assertions` | `SnapDiff::Minitest::Assertions` |
51
+ | `require "capybara_screenshot_diff/minitest"` | `require "snap_diff/integrations/minitest"` |
52
+ | `require "capybara_screenshot_diff/rspec"` | `require "snap_diff/integrations/rspec"` |
53
+ | `require "capybara_screenshot_diff/cucumber"` | `require "snap_diff/integrations/cucumber"` |
54
+ | `require "capybara_screenshot_diff/reporters/html"` | `require "snap_diff/reporters/html"` |
55
+ | `CapybaraScreenshotDiff.serve` (`…/static`) | `SnapDiff.serve` (`require "snap_diff/static"`) |
56
+ | `CapybaraScreenshotDiff.reporters <<` | `SnapDiff::Reporting.register` |
57
+ | `CapybaraScreenshotDiff.finalize_reporters!` | `SnapDiff::Reporting.finalize!` |
58
+
59
+ Note the integration require paths gain an `integrations/` segment — `require "snap_diff/minitest"`
60
+ is a `LoadError`.
46
61
 
47
62
  **What stays the same:**
48
63
  - `screenshot(name)` — still works
@@ -218,7 +233,7 @@ All settings and baselines are compatible with v1.x. Simply pin your Gemfile bac
218
233
 
219
234
  ### Summary Checklist
220
235
 
221
- - [ ] Pin `gem "capybara-screenshot-diff", "2.0.0.alpha1"` in your Gemfile
236
+ - [ ] Pin `gem "capybara-screenshot-diff", "2.0.0.beta2"` (or the latest 2.0.0 prerelease) in your Gemfile
222
237
  - [ ] Run `bundle install`
223
238
  - [ ] Run your test suite to verify no regressions
224
239
  - [ ] (Optional) Migrate config to the `SnapDiff` namespace
@@ -679,7 +694,7 @@ All screenshot baselines are compatible — no data loss.
679
694
 
680
695
  ## Need Help?
681
696
 
682
- - **Documentation:** [README.md](README.md)
697
+ - **Documentation:** [README.md](../README.md)
683
698
  - **Changelog:** [CHANGELOG.md](CHANGELOG.md)
684
699
  - **Issues:** [GitHub Issues](https://github.com/snap-diff/snap_diff-capybara/issues)
685
700
  - **DeepWiki:** [Code Documentation](https://deepwiki.com/snap-diff/snap_diff-capybara)
data/docs/architecture.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This document describes the internal architecture of `capybara-screenshot-diff` — how screenshots are captured, compared, and reported, and how the components fit together.
4
4
 
5
- Since the v2 namespace move (ADR-004), the implementation lives in `lib/snap_diff/` under the `SnapDiff` namespace. The old file paths (`lib/capybara/screenshot/diff/`, `lib/capybara_screenshot_diff/`) remain as thin forwarders, and the old constants resolve to the same objects via `lib/snap_diff/legacy_shims.rb` with a one-time deprecation warning. Class names below use the canonical `SnapDiff::` names, with legacy names noted where they differ.
5
+ Since the v2 namespace move (ADR-004), the implementation lives in `lib/snap_diff/` under the `SnapDiff` namespace. The old file paths (`lib/capybara/screenshot/diff/`, `lib/capybara_screenshot_diff/`) remain as thin forwarders, and the old constants resolve to the same objects via `lib/snap_diff/legacy_shims.rb` with a one-time deprecation warning. Class names below use the canonical `SnapDiff::` names, with legacy names noted where they differ. For the user-facing view of the same surface, see [SnapDiff — the canonical API](snapdiff.md).
6
6
 
7
7
  ## Overview
8
8
 
@@ -14,8 +14,8 @@ Since the v2 namespace move (ADR-004), the implementation lives in `lib/snap_dif
14
14
  │ │
15
15
  ▼ ▼
16
16
  ┌──────────────────────────┐ ┌──────────────────────────┐
17
- CapybaraScreenshotDiff │ │ CapybaraScreenshotDiff
18
- ::DSL (screenshot, etc) │ │ ::AssertionRegistry
17
+ SnapDiff::DSL │ │ SnapDiff::AssertionRegistry
18
+ │ (screenshot, etc) │ │ (SnapDiff.session)
19
19
  └──────────────┬───────────┘ └──────────────┬───────────┘
20
20
  │ │
21
21
  ▼ ▼
@@ -127,6 +127,8 @@ Drivers abstract image processing operations. Shared default behavior lives in t
127
127
 
128
128
  **Auto-detection:** `Utils.detect_available_drivers` tries to load `:vips` first (via `ruby-vips` gem), then `:chunky_png`. The `:auto` driver mode picks the first available.
129
129
 
130
+ **Registry (ADR-008 step 5b):** `SnapDiff::Drivers.loaded` is the canonical driver-class cache — a `name => class` hash filled lazily by `Utils.find_driver_class_for`, and the registration point for custom drivers (the legacy `Capybara::Screenshot::Diff::LOADED_DRIVERS` is an eager same-object alias, so registrations through either land in the same hash). `SnapDiff::Drivers.available` is the canonical read API for the detected list; the value itself still lives on `Capybara::Screenshot::Diff::AVAILABLE_DRIVERS`, which stays the published stubbing point. `SnapDiff::Drivers.for` resolves an options hash to a driver instance. See [Custom drivers](snapdiff.md#custom-drivers).
131
+
130
132
  ### 6. Difference Region Detection
131
133
 
132
134
  **VipsDriver** uses a **difference mask** approach:
@@ -158,7 +160,7 @@ Drivers abstract image processing operations. Shared default behavior lives in t
158
160
 
159
161
  Handles baseline retrieval from git. Uses `git show HEAD:<path>` to extract the committed version. Supports Git LFS via `git lfs smudge`. Returns `false` if the file doesn't exist in VCS (first-run scenario).
160
162
 
161
- ### 9. Reporters (`lib/capybara/screenshot/diff/reporters/default.rb`, `lib/snap_diff/reporters/html.rb`)
163
+ ### 9. Reporters (`lib/snap_diff/reporters/default.rb`, `lib/snap_diff/reporters/html.rb`)
162
164
 
163
165
  **Default reporter:** Generates annotated diff images:
164
166
  - `image.diff.png` — new screenshot with diff region outlined in red
@@ -173,7 +175,7 @@ Handles baseline retrieval from git. Uses `git show HEAD:<path>` to extract the
173
175
  - Keyboard navigation and shortcuts
174
176
  - Responsive layout for mobile
175
177
 
176
- **Custom reporters:** Implement `record(assertions)` and `finalize` methods, then add to `CapybaraScreenshotDiff.reporters`. The process-global reporter lifecycle (registration, notification, finalization) is owned by `SnapDiff::Reporting` (`lib/snap_diff/reporting.rb`); `CapybaraScreenshotDiff.reporters` / `.finalize_reporters!` are thin public shims over it.
178
+ **Custom reporters:** Implement `record(assertions)`, `finalize` and `summary`, then register via `SnapDiff::Reporting.register(reporter)` — the canonical way in, because the append happens under the mutex. The process-global reporter lifecycle (registration, notification, finalization) is owned by `SnapDiff::Reporting` (`lib/snap_diff/reporting.rb`); `CapybaraScreenshotDiff.reporters` / `.finalize_reporters!` are thin public shims over it, and `reporters` stays a mutable array for compatibility (appending directly still works, it just skips the lock). See [Custom reporters](snapdiff.md#custom-reporters).
177
179
 
178
180
  ### 10. Assertion Lifecycle
179
181
 
@@ -189,16 +191,19 @@ Test begins
189
191
  │ └─ delayed=false → validate immediately
190
192
 
191
193
  ├─ teardown:
192
- └─ CapybaraScreenshotDiff.verify
193
- ├─ iterates thread-local assertions
194
- ├─ calls validate on each
195
- ├─ raises ExpectationNotMet on first failure
196
- └─ notifies reporters via mutex-protected snapshot
194
+ ├─ SnapDiff.session.verify
195
+ ├─ iterates the fiber-local assertions
196
+ ├─ calls validate on each
197
+ │ └─ raises SnapDiff::ExpectationNotMet if any differed
198
+
199
+ │ └─ SnapDiff.reset (always, in an ensure)
200
+ │ ├─ SnapDiff::Reporting.notify — mutex-protected reporter snapshot
201
+ │ └─ clears the session
197
202
 
198
- └─ at_exit:
199
- └─ CapybaraScreenshotDiff.finalize_reporters!
203
+ └─ end of suite (Minitest.after_run / RSpec after(:suite) / Cucumber AfterAll):
204
+ └─ SnapDiff::Reporting.finalize!
200
205
  ├─ Generates HTML report (if reporter registered)
201
- └─ Prints summary
206
+ └─ Prints each reporter's summary
202
207
  ```
203
208
 
204
209
  ### 11. Thread Safety
@@ -209,12 +214,16 @@ Test begins
209
214
  | Reporter notification | Mutex-protected snapshot of reporter list before iteration |
210
215
  | HTML reporter internals | Mutex protecting `@failures`, `@total`, `@finalized` |
211
216
  | Screenshot naming | Per-thread `ScreenshotNamer` instance |
212
- | Global configuration | `mattr_accessor` — must be set before tests run, not mutated during parallel execution |
217
+ | Global configuration | One process-wide `SnapDiff::Config` instance — must be set before tests run, not mutated during parallel execution |
213
218
  | File system | Atomic `FileUtils.mv`, unique paths per screenshot name + counter, thread-safe `mkpath` |
214
219
 
215
220
  ### 12. Configuration System
216
221
 
217
- Configuration uses Ruby's `mattr_accessor` (pure Ruby implementation in `lib/capybara/screenshot/diff/config_legacy.rb`, deliberately kept at the old path as the single source of truth for settings storage) and is organized into two namespaces:
222
+ Since ADR-008 step 1 the storage ownership is inverted from the original v2 consolidation: **`SnapDiff::Config` (`lib/snap_diff/config.rb`) IS the storage** one eagerly-created instance, reachable as `SnapDiff.config`, holding every setting as a plain `attr_accessor`. It is the leaf of the config require graph and requires nothing that leads back to either entry point.
223
+
224
+ The legacy `Capybara::Screenshot.*` / `Capybara::Screenshot::Diff.*` accessors are thin delegators generated from `Config::MAPPING` (both singleton and instance methods, matching what `mattr_accessor` used to define) that forward to that one object. One storage, two views — a write through either surface is visible through the other structurally, not by synchronization. `lib/capybara/screenshot/diff/config_legacy.rb` remains at the old path, but it now installs the delegating surface rather than owning the state.
225
+
226
+ The two legacy views are organized into two namespaces:
218
227
 
219
228
  **`Capybara::Screenshot`** — capture settings:
220
229
  - `window_size`, `stability_time_limit`, `blur_active_element`, `hide_caret`, `disable_animations`
@@ -225,7 +234,11 @@ Configuration uses Ruby's `mattr_accessor` (pure Ruby implementation in `lib/cap
225
234
  - `driver`, `tolerance`, `color_distance_limit`, `perceptual_threshold`, `shift_distance_limit`
226
235
  - `area_size_limit`, `skip_area`, `fail_if_new`, `fail_on_difference`, `delayed`
227
236
 
228
- The `Diff.configure` block helper provides a convenient way to set both namespaces at once. Since v2, `SnapDiff::Config` (`lib/snap_diff/config.rb`) additionally exposes all 27 settings as one flat object via `SnapDiff.config` / `SnapDiff.configure { |config| ... }` it holds no state of its own, every accessor forwards to the legacy `mattr_accessor` storage, so both views stay consistent.
237
+ The canonical way in is `SnapDiff.configure { |config| ... }` (all 27 settings flat on one object). `SnapDiff.start` and `Capybara::Screenshot::Diff.configure` are the two-holder block shape over the same storage since ADR-008 step 7b, `Diff.configure` forwards to `SnapDiff.start` rather than the other way round.
238
+
239
+ `Config` also owns the derived values that used to live on the legacy modules: `active?` (ex `Capybara::Screenshot.active?`), `screenshot_area` / `screenshot_area_abs`, and `default_options` (ex `Capybara::Screenshot::Diff.default_options`, the option hash handed to `SnapDiff::Comparison`). The legacy module methods one-line forward here.
240
+
241
+ **Default timing contract:** every default is evaluated once, in `Config#initialize`, which runs at require time of `config.rb` — the same load moment the old `mattr_accessor` default blocks evaluated at. `fail_if_new` (from `ENV["CI"]`) and `root` (from `Rails.root`) must never become lazy read-time defaults. The one deliberately live value is `default_options[:wait]`, a method-body read of `Capybara.default_max_wait_time`.
229
242
 
230
243
  ## File Layout
231
244
 
@@ -234,7 +247,9 @@ lib/
234
247
  snap_diff.rb # SnapDiff module: compare/start/configure/config
235
248
  snap_diff/ # Canonical implementation (v2)
236
249
  dsl.rb # screenshot(), screenshot_group(), etc.
237
- config.rb # SnapDiff::Config — flat view over all 27 settings
250
+ config.rb # SnapDiff::Config — THE storage for all 27 settings
251
+ errors.rb # Error / ExpectationNotMet / UnstableImage / WindowSizeMismatchError
252
+ region.rb # SnapDiff::Region — bounding box (+ eager top-level ::Region alias)
238
253
  deprecation.rb # Warn-once-per-constant machinery
239
254
  legacy_shims.rb # const_missing forwarders for the old namespaces
240
255
  comparison.rb # Layered comparison engine (ex-ImageCompare)
@@ -272,18 +287,19 @@ lib/
272
287
  minitest.rb # Minitest assertions integration
273
288
  rspec.rb # RSpec matcher integration
274
289
  cucumber.rb # Cucumber World integration
275
- capybara_screenshot_diff.rb # Umbrella entry point + error classes
290
+ capybara_screenshot_diff.rb # Umbrella entry point + eager error-class aliases
276
291
  capybara_screenshot_diff/ # Legacy paths — mostly thin forwarders
277
292
  minitest.rb / rspec.rb / cucumber.rb # Legacy entry points (load the full gem)
278
293
  screenshot_assertion.rb # CapybaraScreenshotDiff session/reporter shims
279
294
  ... # Everything else forwards to snap_diff/
280
295
  capybara/screenshot/diff.rb # Convenience require (loads minitest)
281
296
  capybara/screenshot/diff/
282
- config_legacy.rb # mattr_accessor settings storage (source of truth)
283
- region.rb # Bounding box region value object (top-level Region)
284
- reporters/default.rb # Default annotated-image reporter
297
+ config_legacy.rb # Legacy accessor surface, delegating to SnapDiff::Config
298
+ region.rb # Forwarder to snap_diff/region.rb
285
299
  version.rb # Capybara::Screenshot::Diff::VERSION (gemspec reads it)
286
300
  ... # Everything else forwards to snap_diff/
287
301
  ```
288
302
 
289
- The legacy `Capybara::Screenshot::Diff::*` and `CapybaraScreenshotDiff::*` constants resolve lazily via `snap_diff/legacy_shims.rb` (`const_missing`), pointing at the same objects with a one-time deprecation warning. See [UPGRADING.md](UPGRADING.md) for the migration guide.
303
+ Most legacy `Capybara::Screenshot::Diff::*` and `CapybaraScreenshotDiff::*` constants resolve lazily via `snap_diff/legacy_shims.rb` (`const_missing`), pointing at the same objects with a one-time deprecation warning. The error classes are the deliberate exception: they are **eager** same-object aliases, because `rescue` clauses and `defined?` / `const_defined?` feature detection in adopter code must keep behaving exactly as before (`const_defined?` never triggers `const_missing`). Same for `LOADED_DRIVERS`, pinned as an eager alias of `SnapDiff::Drivers.loaded` so user registrations through the old constant are not silently dropped.
304
+
305
+ See [SnapDiff — the canonical API](snapdiff.md) for the canonical surface, and [UPGRADING.md](UPGRADING.md) for the migration guide.
@@ -4,10 +4,19 @@
4
4
 
5
5
  ```ruby
6
6
  # test/test_helper.rb
7
- require 'capybara_screenshot_diff/static'
7
+ require 'snap_diff/static'
8
+
9
+ SnapDiff.serve("_site") # or "public", "build", "dist"
10
+ ```
11
+
12
+ <details>
13
+ <summary>Legacy names (still supported)</summary>
8
14
 
9
- CapybaraScreenshotDiff.serve("_site") # or "public", "build", "dist"
15
+ ```ruby
16
+ require 'capybara_screenshot_diff/static'
17
+ CapybaraScreenshotDiff.serve("_site")
10
18
  ```
19
+ </details>
11
20
 
12
21
  This sets up Capybara to serve static files and configures screenshot paths automatically.
13
22
 
@@ -24,7 +33,8 @@ Only commit the baseline screenshots (e.g., `homepage.png`). The `.base.png`, `.
24
33
  Add to your test helper:
25
34
 
26
35
  ```ruby
27
- require 'capybara_screenshot_diff/reporters/html'
36
+ require 'snap_diff/reporters/html' # canonical
37
+ # require 'capybara_screenshot_diff/reporters/html' # legacy, same thing
28
38
  ```
29
39
 
30
40
  ### 2. Reusable composite action (recommended)
@@ -2,10 +2,25 @@
2
2
 
3
3
  ## Quick Setup
4
4
 
5
- Configure all settings in one place using the `configure` helper:
5
+ **Canonical (v2):** every setting lives on one flat object, `SnapDiff.config`.
6
6
 
7
7
  ```ruby
8
8
  # In test_helper.rb or rails_helper.rb
9
+ SnapDiff.configure do |config|
10
+ config.window_size = [1280, 1024]
11
+ config.stability_time_limit = 1
12
+ config.blur_active_element = true
13
+ config.hide_caret = true
14
+ config.driver = :vips
15
+ config.tolerance = 0.0005
16
+ config.color_distance_limit = 15
17
+ end
18
+ ```
19
+
20
+ **Legacy (still supported):** the two-holder block, split across `Capybara::Screenshot` and
21
+ `Capybara::Screenshot::Diff`.
22
+
23
+ ```ruby
9
24
  Capybara::Screenshot::Diff.configure do |screenshot, diff|
10
25
  screenshot.window_size = [1280, 1024]
11
26
  screenshot.stability_time_limit = 1
@@ -17,6 +32,20 @@ Capybara::Screenshot::Diff.configure do |screenshot, diff|
17
32
  end
18
33
  ```
19
34
 
35
+ `SnapDiff::Config` **is** the storage; the legacy accessors are thin delegators onto it. There is
36
+ one source of truth, so a write through either surface is visible through the other — mixing them
37
+ is safe, and you can migrate a suite one line at a time:
38
+
39
+ ```ruby
40
+ SnapDiff.config.window_size = [1280, 1024]
41
+ Capybara::Screenshot.window_size # => [1280, 1024]
42
+ ```
43
+
44
+ Every option name below is identical on both surfaces — only the receiver changes. The one
45
+ exception: `Capybara::Screenshot.enabled` is `SnapDiff.config.screenshot_enabled`, because
46
+ `SnapDiff.config.enabled` is taken by `Capybara::Screenshot::Diff.enabled`. See
47
+ [SnapDiff — the canonical API](snapdiff.md) for the full SnapDiff-native surface.
48
+
20
49
  **Note:** `fail_if_new` defaults to `true` in CI environments (when `ENV['CI']` is set). New screenshots are allowed locally but rejected in CI — no configuration needed.
21
50
 
22
51
  **Note:** Setting `Capybara::Screenshot.enabled = false` is sufficient to disable all screenshots. There is no need to define no-op modules or monkey-patch the gem.
@@ -77,7 +106,7 @@ screenshot 'dashboard', color_distance_limit: 15
77
106
 
78
107
  **Tier 1 — Zero config (works immediately):**
79
108
  `blur_active_element`, `hide_caret`, and `fail_if_new` (in CI) are enabled by default.
80
- Just `require 'capybara_screenshot_diff/minitest'` and call `screenshot`.
109
+ Just `require 'snap_diff/integrations/minitest'` (legacy: `capybara_screenshot_diff/minitest`) and call `screenshot`.
81
110
 
82
111
  **Tier 2 — Set when tests are flaky:**
83
112
 
data/docs/drivers.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Image Processing Drivers
2
2
 
3
+ > **Canonical equivalents.** Global settings shown here as
4
+ > `Capybara::Screenshot::Diff.<option> = …` are also `SnapDiff.config.<option> = …` — same
5
+ > option names, same storage, either surface works. Writing your own driver? See
6
+ > [Custom drivers](snapdiff.md#custom-drivers) for the `SnapDiff::Driver` mixin and how
7
+ > registration in `SnapDiff::Drivers.loaded` works.
8
+
3
9
  ## Perceptual color comparison (VIPS only)
4
10
 
5
11
  By default, color differences are measured using raw RGB channel distance. This can produce
@@ -1,5 +1,19 @@
1
1
  # Framework Setup
2
2
 
3
+ > **Canonical equivalents.** This page uses the legacy `CapybaraScreenshotDiff` names, which keep
4
+ > working. Each has a `SnapDiff` home:
5
+ >
6
+ > | This page | Canonical |
7
+ > |-----------|-----------|
8
+ > | `require "capybara_screenshot_diff/minitest"` | `require "snap_diff/integrations/minitest"` |
9
+ > | `require "capybara_screenshot_diff/rspec"` | `require "snap_diff/integrations/rspec"` |
10
+ > | `require "capybara_screenshot_diff/cucumber"` | `require "snap_diff/integrations/cucumber"` |
11
+ > | `CapybaraScreenshotDiff::DSL` | `SnapDiff::DSL` |
12
+ > | `CapybaraScreenshotDiff::Minitest::Assertions` | `SnapDiff::Minitest::Assertions` |
13
+ > | `CapybaraScreenshotDiff.finalize_reporters!` | `SnapDiff::Reporting.finalize!` |
14
+ >
15
+ > The canonical setup, written out in full, is in [SnapDiff — the canonical API](snapdiff.md).
16
+
3
17
  ## Including DSL
4
18
 
5
19
  To use the screenshot capturing and change detection features in your tests, include the `CapybaraScreenshotDiff::DSL` in your test classes. It provides the `screenshot` method to capture and compare screenshots.
@@ -76,12 +90,16 @@ end
76
90
 
77
91
  ## Custom Test Frameworks
78
92
 
79
- Minitest, RSpec, and Cucumber are supported out of the box. For other frameworks, call `finalize_reporters!` in your framework's "after suite" hook:
93
+ Minitest, RSpec, and Cucumber are supported out of the box. For other frameworks, call the
94
+ end-of-suite hook yourself:
80
95
 
81
96
  ```ruby
82
- CapybaraScreenshotDiff.finalize_reporters!
97
+ SnapDiff::Reporting.finalize! # canonical
98
+ CapybaraScreenshotDiff.finalize_reporters! # legacy, same thing
83
99
  ```
84
100
 
85
- This generates the HTML report and prints the summary.
101
+ This generates the HTML report and prints the summary. A framework also needs the per-test
102
+ lifecycle wired up — see
103
+ [Frameworks other than Minitest/RSpec/Cucumber](snapdiff.md#frameworks-other-than-minitestrspeccucumber).
86
104
 
87
105
  [← Back to README](../README.md)
data/docs/reporters.md CHANGED
@@ -6,7 +6,8 @@ Generate an interactive Web UI report of screenshot differences:
6
6
 
7
7
  ```ruby
8
8
  # Add to test_helper.rb — one line, that's it
9
- require 'capybara_screenshot_diff/reporters/html'
9
+ require 'snap_diff/reporters/html' # canonical
10
+ # require 'capybara_screenshot_diff/reporters/html' # legacy, same thing
10
11
  ```
11
12
 
12
13
  After running tests, open the report (generated only when there are failures):
@@ -21,7 +22,7 @@ The report includes a sidebar with thumbnails, side-by-side comparison with diff
21
22
 
22
23
  ## Custom Reporters
23
24
 
24
- Build your own reporter by implementing `record` and `finalize`:
25
+ Build your own reporter by implementing `record`, `finalize` and `summary`:
25
26
 
26
27
  ```ruby
27
28
  class MyReporter
@@ -33,14 +34,28 @@ class MyReporter
33
34
  end
34
35
 
35
36
  def finalize
36
- # called once at process exit — write summary, upload report, etc.
37
+ # called once at end of suite — write summary, upload report, etc.
38
+ end
39
+
40
+ def summary
41
+ # printed to stdout after finalize; return nil to print nothing
42
+ nil
37
43
  end
38
44
  end
39
45
 
40
46
  # Register in test_helper.rb
41
- CapybaraScreenshotDiff.reporters << MyReporter.new
47
+ SnapDiff::Reporting.register(MyReporter.new) # canonical — appends under the mutex
48
+ # CapybaraScreenshotDiff.reporters << MyReporter.new # legacy, same list, skips the lock
42
49
  ```
43
50
 
44
- Reporters are notified before assertions are cleared on each test teardown. `finalize` is called via `at_exit`.
51
+ Reporters are notified before assertions are cleared on each test teardown. `finalize` runs from
52
+ the framework's end-of-suite hook (`Minitest.after_run`, RSpec `after(:suite)`, Cucumber
53
+ `AfterAll`), which calls `SnapDiff::Reporting.finalize!`.
54
+
55
+ **Do implement `summary`.** `finalize!` calls it unconditionally, so a reporter without it is
56
+ finalized and then warned about. A reporter that raises is warned about and skipped — the others
57
+ still run.
58
+
59
+ Full details in [Custom reporters](snapdiff.md#custom-reporters).
45
60
 
46
61
  [← Back to README](../README.md)