snap_diff-capybara 0.0.1 → 2.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +190 -0
- data/CODE_OF_CONDUCT.md +129 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +65 -0
- data/capybara-screenshot-diff.gemspec +29 -0
- data/docs/RELEASE_PREP.md +44 -0
- data/docs/UPGRADING.md +702 -0
- data/docs/architecture.md +289 -0
- data/docs/ci-integration.md +238 -0
- data/docs/configuration.md +395 -0
- data/docs/docker-testing.md +24 -0
- data/docs/drivers.md +102 -0
- data/docs/framework-setup.md +87 -0
- data/docs/images/snap_diff_annotated.png +0 -0
- data/docs/images/snap_diff_web_ui.png +0 -0
- data/docs/migration-guide.md +286 -0
- data/docs/organization.md +204 -0
- data/docs/reporters.md +46 -0
- data/docs/thread_safety.md +112 -0
- data/gems.rb +39 -0
- data/lib/capybara/screenshot/diff/annotation_service.rb +7 -0
- data/lib/capybara/screenshot/diff/area_calculator.rb +7 -0
- data/lib/capybara/screenshot/diff/browser_helpers.rb +7 -0
- data/lib/capybara/screenshot/diff/config_legacy.rb +113 -0
- data/lib/capybara/screenshot/diff/cucumber.rb +3 -0
- data/lib/capybara/screenshot/diff/difference.rb +8 -0
- data/lib/capybara/screenshot/diff/drivers/base_driver.rb +9 -0
- data/lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb +7 -0
- data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +7 -0
- data/lib/capybara/screenshot/diff/drivers.rb +9 -0
- data/lib/capybara/screenshot/diff/image_compare.rb +12 -0
- data/lib/capybara/screenshot/diff/image_preprocessor.rb +7 -0
- data/lib/capybara/screenshot/diff/os.rb +14 -0
- data/lib/capybara/screenshot/diff/region.rb +107 -0
- data/lib/capybara/screenshot/diff/reporters/default.rb +109 -0
- data/lib/capybara/screenshot/diff/screenshot_matcher.rb +7 -0
- data/lib/capybara/screenshot/diff/screenshoter.rb +7 -0
- data/lib/capybara/screenshot/diff/stable_screenshoter.rb +7 -0
- data/lib/capybara/screenshot/diff/utils.rb +7 -0
- data/lib/capybara/screenshot/diff/vcs.rb +7 -0
- data/lib/capybara/screenshot/diff/version.rb +15 -0
- data/lib/capybara/screenshot/diff.rb +3 -0
- data/lib/capybara-screenshot-diff.rb +3 -0
- data/lib/capybara_screenshot_diff/attempts_reporter.rb +7 -0
- data/lib/capybara_screenshot_diff/cucumber.rb +8 -0
- data/lib/capybara_screenshot_diff/dsl.rb +12 -0
- data/lib/capybara_screenshot_diff/error_with_filtered_backtrace.rb +8 -0
- data/lib/capybara_screenshot_diff/minitest.rb +14 -0
- data/lib/capybara_screenshot_diff/reporters/html.rb +7 -0
- data/lib/capybara_screenshot_diff/rspec.rb +8 -0
- data/lib/capybara_screenshot_diff/screenshot_assertion.rb +71 -0
- data/lib/capybara_screenshot_diff/screenshot_namer.rb +7 -0
- data/lib/capybara_screenshot_diff/snap.rb +7 -0
- data/lib/capybara_screenshot_diff/snap_manager.rb +7 -0
- data/lib/capybara_screenshot_diff/static.rb +9 -0
- data/lib/capybara_screenshot_diff.rb +50 -0
- data/lib/snap_diff/annotation_service.rb +84 -0
- data/lib/snap_diff/area_calculator.rb +56 -0
- data/lib/snap_diff/attempts_reporter.rb +51 -0
- data/lib/snap_diff/browser_helpers.rb +121 -0
- data/lib/snap_diff/capture/viewport.rb +40 -0
- data/lib/snap_diff/comparison.rb +238 -0
- data/lib/snap_diff/comparison_result.rb +104 -0
- data/lib/snap_diff/config.rb +78 -0
- data/lib/snap_diff/deprecation.rb +84 -0
- data/lib/snap_diff/driver.rb +37 -0
- data/lib/snap_diff/drivers/chunky_png_driver.rb +298 -0
- data/lib/snap_diff/drivers/vips_driver.rb +171 -0
- data/lib/snap_diff/drivers.rb +14 -0
- data/lib/snap_diff/dsl.rb +143 -0
- data/lib/snap_diff/error_with_filtered_backtrace.rb +32 -0
- data/lib/snap_diff/image_preprocessor.rb +68 -0
- data/lib/snap_diff/integrations/cucumber.rb +22 -0
- data/lib/snap_diff/integrations/minitest.rb +70 -0
- data/lib/snap_diff/integrations/rspec.rb +68 -0
- data/lib/snap_diff/legacy_shims.rb +99 -0
- data/lib/snap_diff/os.rb +17 -0
- data/lib/snap_diff/reporters/html.rb +143 -0
- data/lib/snap_diff/reporters/templates/report.html.erb +463 -0
- data/lib/snap_diff/reporting.rb +53 -0
- data/lib/snap_diff/screenshot_assertion.rb +143 -0
- data/lib/snap_diff/screenshot_matcher.rb +113 -0
- data/lib/snap_diff/screenshot_namer.rb +81 -0
- data/lib/snap_diff/screenshoter.rb +129 -0
- data/lib/snap_diff/snap.rb +66 -0
- data/lib/snap_diff/snap_manager.rb +125 -0
- data/lib/snap_diff/stable_screenshoter.rb +103 -0
- data/lib/snap_diff/static.rb +11 -0
- data/lib/snap_diff/utils.rb +38 -0
- data/lib/snap_diff/vcs.rb +35 -0
- data/lib/snap_diff/version.rb +5 -0
- data/lib/snap_diff.rb +65 -0
- metadata +160 -10
- data/README.md +0 -3
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
## Quick Setup
|
|
4
|
+
|
|
5
|
+
Configure all settings in one place using the `configure` helper:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
# In test_helper.rb or rails_helper.rb
|
|
9
|
+
Capybara::Screenshot::Diff.configure do |screenshot, diff|
|
|
10
|
+
screenshot.window_size = [1280, 1024]
|
|
11
|
+
screenshot.stability_time_limit = 1
|
|
12
|
+
screenshot.blur_active_element = true
|
|
13
|
+
screenshot.hide_caret = true
|
|
14
|
+
diff.driver = :vips
|
|
15
|
+
diff.tolerance = 0.0005
|
|
16
|
+
diff.color_distance_limit = 15
|
|
17
|
+
end
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**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
|
+
|
|
22
|
+
**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.
|
|
23
|
+
|
|
24
|
+
## Recommended tolerance values
|
|
25
|
+
|
|
26
|
+
| Use Case | VIPS `tolerance` | ChunkyPNG `color_distance_limit` | `stability_time_limit` |
|
|
27
|
+
|----------|-----------------|--------------------------------|----------------------|
|
|
28
|
+
| Animated/complex pages | 0.01 | 30 | 2s |
|
|
29
|
+
| Standard Rails apps | 0.001 (default) | 15 | 1s |
|
|
30
|
+
| Pixel-perfect design tests | 0.0001 | 5 | 1s |
|
|
31
|
+
|
|
32
|
+
**Note:** VIPS defaults to `tolerance: 0.001` (allows 0.1% pixel difference). ChunkyPNG has no default tolerance.
|
|
33
|
+
|
|
34
|
+
## Choosing the Right Color Comparison Method
|
|
35
|
+
|
|
36
|
+
**Important:** `perceptual_threshold`, `color_distance_limit`, and `tolerance` serve different purposes. Use this decision tree:
|
|
37
|
+
|
|
38
|
+
### Step 1: Choose color comparison method (pick ONE)
|
|
39
|
+
|
|
40
|
+
| Method | Scale | Driver | Best for |
|
|
41
|
+
|--------|-------|--------|----------|
|
|
42
|
+
| `perceptual_threshold` | 0-100+ (dE00) | VIPS only | Cross-OS/browser font rendering, anti-aliasing |
|
|
43
|
+
| `color_distance_limit` | 0-510 (RGBA Euclidean) | VIPS, ChunkyPNG | Legacy setups, fine-grained RGB control |
|
|
44
|
+
|
|
45
|
+
**Recommendation:** Use `perceptual_threshold: 2.0` for most cases. It matches human perception and needs less tuning.
|
|
46
|
+
|
|
47
|
+
**⚠️ Color comparison methods are exclusive:** `perceptual_threshold` and `color_distance_limit` cannot both be active — if you set both, `perceptual_threshold` wins and `color_distance_limit` is ignored. However, `tolerance` works with **both** methods and is applied by default for VIPS (0.001). This means even with `perceptual_threshold: 2.0`, the `tolerance: 0.001` default still filters results.
|
|
48
|
+
|
|
49
|
+
### Step 2: Set tolerance (optional, independent)
|
|
50
|
+
|
|
51
|
+
| Setting | What it does | Scale |
|
|
52
|
+
|---------|--------------|-------|
|
|
53
|
+
| `tolerance` | Maximum allowed *ratio* of different pixels (VIPS) or diff bounding box (ChunkyPNG) | 0.0-1.0 |
|
|
54
|
+
|
|
55
|
+
**Example:** `tolerance: 0.001` allows 0.1% of the image to differ (e.g., 125 pixels in a 1280×1024 screenshot).
|
|
56
|
+
|
|
57
|
+
**Key difference:**
|
|
58
|
+
- `perceptual_threshold` / `color_distance_limit` → **"how different can a pixel be?"**
|
|
59
|
+
- `tolerance` → **"how many pixels can differ?"**
|
|
60
|
+
|
|
61
|
+
**⚠️ Driver difference:** VIPS counts actual different pixels. ChunkyPNG counts the bounding box area around differences — a single pixel diff creates a box, and the entire box area counts against tolerance. This makes ChunkyPNG stricter with the same tolerance value.
|
|
62
|
+
|
|
63
|
+
### Quick start
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
# Modern approach (recommended)
|
|
67
|
+
screenshot 'dashboard', perceptual_threshold: 2.0
|
|
68
|
+
|
|
69
|
+
# Allow small noise regions
|
|
70
|
+
screenshot 'dashboard', perceptual_threshold: 2.0, tolerance: 0.001
|
|
71
|
+
|
|
72
|
+
# Legacy ChunkyPNG setup
|
|
73
|
+
screenshot 'dashboard', color_distance_limit: 15
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Configuration Tiers
|
|
77
|
+
|
|
78
|
+
**Tier 1 — Zero config (works immediately):**
|
|
79
|
+
`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`.
|
|
81
|
+
|
|
82
|
+
**Tier 2 — Set when tests are flaky:**
|
|
83
|
+
|
|
84
|
+
| Setting | When to use |
|
|
85
|
+
|---------|-------------|
|
|
86
|
+
| `window_size` | Screenshots differ between machines due to different browser sizes |
|
|
87
|
+
| `tolerance` | Sub-pixel rendering differences cause false positives |
|
|
88
|
+
| `skip_area` | Dynamic content (timestamps, ads) changes between runs |
|
|
89
|
+
| `stability_time_limit` | Animations or loading states cause inconsistent captures |
|
|
90
|
+
|
|
91
|
+
**Tier 3 — Advanced tuning:**
|
|
92
|
+
|
|
93
|
+
| Setting | When to use |
|
|
94
|
+
|---------|-------------|
|
|
95
|
+
| `perceptual_threshold` | Anti-aliasing false positives across OS/browser versions |
|
|
96
|
+
| `shift_distance_limit` | Content shifts by a few pixels (ChunkyPNG only) |
|
|
97
|
+
| `area_size_limit` | Allow small diff regions below a pixel count |
|
|
98
|
+
| `color_distance_limit` | Fine-tune raw RGB channel tolerance |
|
|
99
|
+
| `median_filter_window_size` | Smooth noise before comparison (VIPS only) |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Common Options
|
|
104
|
+
|
|
105
|
+
### Screen size
|
|
106
|
+
|
|
107
|
+
You can specify the desired screen size using
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
Capybara::Screenshot.window_size = [1024, 768]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This will force the screen shots to the given size, and skip taking screen shots
|
|
114
|
+
unless the desired window size can be achieved.
|
|
115
|
+
|
|
116
|
+
### Disabling screen shots
|
|
117
|
+
|
|
118
|
+
If you want to skip taking screen shots, set
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
Capybara::Screenshot.enabled = false
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
You can of course set this by an environment variable
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
Capybara::Screenshot.enabled = ENV['TAKE_SCREENSHOTS']
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Disabling diff
|
|
131
|
+
|
|
132
|
+
If you want to skip the assertion for change in the screen shot, set
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
Capybara::Screenshot::Diff.enabled = false
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Using an environment variable
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
Capybara::Screenshot::Diff.enabled = ENV['COMPARE_SCREENSHOTS']
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Tolerate screenshot differences
|
|
145
|
+
|
|
146
|
+
To allow screenshot differences, but still fail on functional errors, you can set the following option:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
Capybara::Screenshot::Diff.fail_on_difference = false
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
It defaults to `true`. This can be useful in continuous integration to a generate a screenshot difference
|
|
153
|
+
report while still reporting functional errors.
|
|
154
|
+
|
|
155
|
+
### Does not tolerate new screenshots
|
|
156
|
+
|
|
157
|
+
To fail the test if a new screenshot is taken, set the following option:
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
Capybara::Screenshot::Diff.fail_if_new = true
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
If `fail_if_new` is set to `true`, the test will fail if a new screenshot is taken
|
|
164
|
+
that does not have a corresponding previous image to compare against.
|
|
165
|
+
This can be useful in situations where you want to ensure
|
|
166
|
+
that every screenshot taken by your tests corresponds to an expected state of your application.
|
|
167
|
+
|
|
168
|
+
### Marks new screenshots as pending
|
|
169
|
+
|
|
170
|
+
To mark tests as pending (skipped) if a new screenshot is taken without a baseline, set:
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
Capybara::Screenshot::Diff.pending_if_new = true
|
|
174
|
+
# Required in CI, because fail_if_new defaults to true there and raises before
|
|
175
|
+
# the pending marker is applied.
|
|
176
|
+
Capybara::Screenshot::Diff.fail_if_new = false
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
If `pending_if_new` is set to `true`, the test will be marked as skipped in teardown
|
|
180
|
+
when a new screenshot has no committed baseline to compare against.
|
|
181
|
+
This is complementary to `fail_if_new` (which raises immediately); `fail_if_new` takes precedence since it raises first.
|
|
182
|
+
This option is useful when you want to record new screenshots without blocking CI, but still track them as needing review.
|
|
183
|
+
|
|
184
|
+
### Screen shot save path
|
|
185
|
+
|
|
186
|
+
By default, `Capybara::Screenshot::Diff` saves screenshots to a
|
|
187
|
+
`doc/screenshots` folder, relative to either `Rails.root` (if you're in Rails),
|
|
188
|
+
or your current directory otherwise.
|
|
189
|
+
|
|
190
|
+
If you want to change where screenshots are saved to, then there are two
|
|
191
|
+
configuration options that that are relevant.
|
|
192
|
+
|
|
193
|
+
The most likely one you'll want to modify is ...
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
Capybara::Screenshot.save_path = "other/path"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The `save_path` option is relative to `Capybara::Screenshot.root`.
|
|
200
|
+
|
|
201
|
+
`Capybara::Screenshot.root` defaults to either `Rails.root` (if you're in
|
|
202
|
+
Rails) or your current directory. You can change it to something entirely
|
|
203
|
+
different if necessary, such as when using an alternative web framework.
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
Capybara::Screenshot.root = Hanami.root
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Screen shot stability
|
|
210
|
+
|
|
211
|
+
To ensure that animations are finished before saving a screen shot, you can add
|
|
212
|
+
a stability time limit. If the stability time limit is set, a second screen
|
|
213
|
+
shot will be taken and compared to the first. This is repeated until two
|
|
214
|
+
subsequent screen shots are identical.
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
Capybara::Screenshot.stability_time_limit = 0.1
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
This can be overridden on a single screenshot:
|
|
221
|
+
|
|
222
|
+
```ruby
|
|
223
|
+
test 'stability_time_limit' do
|
|
224
|
+
visit '/'
|
|
225
|
+
screenshot 'index', stability_time_limit: 0.5
|
|
226
|
+
end
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Maximum wait limit
|
|
230
|
+
|
|
231
|
+
When the `stability_time_limit` is set, but no stable screenshot can be taken, a timeout occurs.
|
|
232
|
+
The timeout occurs after `Capybara.default_max_wait_time`, but can be overridden by an option.
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
test 'max wait time' do
|
|
236
|
+
visit '/'
|
|
237
|
+
screenshot 'index', wait: 20.seconds
|
|
238
|
+
end
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Hiding the caret for active input elements
|
|
242
|
+
|
|
243
|
+
In Chrome the screenshot includes the blinking input cursor. This can make it impossible to get a
|
|
244
|
+
stable screenshot. To get around this you can set the `hide caret` option:
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
Capybara::Screenshot.hide_caret = true
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
This will make the cursor (caret) transparent (invisible), so the blinking does not delay the screen shot.
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
### Removing focus from the active element
|
|
254
|
+
|
|
255
|
+
Another way to avoid the cursor blinking is to set the `blur_active_element` option:
|
|
256
|
+
|
|
257
|
+
```ruby
|
|
258
|
+
Capybara::Screenshot.blur_active_element = true
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
This will remove the focus from the active element, removing the blinking cursor.
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
### Allowed color distance
|
|
266
|
+
|
|
267
|
+
Sometimes you want to allow small differences in the images. For example, Chrome renders the same
|
|
268
|
+
page slightly differently sometimes. You can set set the color difference threshold for the
|
|
269
|
+
comparison using the `color_distance_limit` option to the `screenshot` method:
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
test 'color threshold' do
|
|
273
|
+
visit '/'
|
|
274
|
+
screenshot 'index', color_distance_limit: 30
|
|
275
|
+
end
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
The difference is calculated as the euclidean distance. You can also set this globally:
|
|
279
|
+
|
|
280
|
+
```ruby
|
|
281
|
+
Capybara::Screenshot::Diff.color_distance_limit = 42
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
### Allowed shift distance
|
|
286
|
+
|
|
287
|
+
Sometimes you want to allow small movements in the images. For example, jquery-tablesorter
|
|
288
|
+
renders the same table slightly differently sometimes. You can set set the shift distance
|
|
289
|
+
threshold for the comparison using the `shift_distance_limit` option to the `screenshot`
|
|
290
|
+
method:
|
|
291
|
+
|
|
292
|
+
```ruby
|
|
293
|
+
test 'color threshold' do
|
|
294
|
+
visit '/'
|
|
295
|
+
screenshot 'index', shift_distance_limit: 2
|
|
296
|
+
end
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
The difference is calculated as maximum distance in either the X or the Y axis.
|
|
300
|
+
You can also set this globally:
|
|
301
|
+
|
|
302
|
+
```ruby
|
|
303
|
+
Capybara::Screenshot::Diff.shift_distance_limit = 1
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Note:** For each increase in `shift_distance_limit` more pixels are searched for a matching color value, and
|
|
307
|
+
this will impact performance **severely** if a match cannot be found.
|
|
308
|
+
|
|
309
|
+
If `shift_distance_limit` is `nil` shift distance is not measured. If `shift_distance_limit` is set,
|
|
310
|
+
even to `0`, shift distance is measured and reported on image differences.
|
|
311
|
+
|
|
312
|
+
### Allowed difference size
|
|
313
|
+
|
|
314
|
+
You can set set a threshold for the differing area size for the comparison
|
|
315
|
+
using the `area_size_limit` option to the `screenshot` method:
|
|
316
|
+
|
|
317
|
+
```ruby
|
|
318
|
+
test 'area threshold' do
|
|
319
|
+
visit '/'
|
|
320
|
+
screenshot 'index', area_size_limit: 17
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The difference is calculated as `width * height`. You can also set this globally:
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
Capybara::Screenshot::Diff.area_size_limit = 42
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
### Skipping an area
|
|
332
|
+
|
|
333
|
+
Sometimes you have expected change that you want to ignore.
|
|
334
|
+
You can use the `skip_area` option with `[left, top, right, bottom]`
|
|
335
|
+
or css selector like `'#footer'` or `'.container .skipped_element'` to the `screenshot` method to ignore an area.
|
|
336
|
+
Be aware that if the selector is not in the page then the library will wait the default wait time for it to appear.
|
|
337
|
+
Therefore, it is best to only use css selectors for skip_areas you know will be in the page:
|
|
338
|
+
|
|
339
|
+
```ruby
|
|
340
|
+
test 'unstable area' do
|
|
341
|
+
visit '/'
|
|
342
|
+
screenshot 'index', skip_area: [[17, 6, 27, 16], '.container .skipped_element', '#footer']
|
|
343
|
+
end
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
The arguments are `[left, top, right, bottom]` for the area you want to ignore. You can also set this globally:
|
|
347
|
+
|
|
348
|
+
```ruby
|
|
349
|
+
Capybara::Screenshot::Diff.skip_area = [0, 0, 64, 48]
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
If you need to ignore multiple areas:
|
|
353
|
+
|
|
354
|
+
```ruby
|
|
355
|
+
screenshot 'index', skip_area: [[0, 0, 64, 48], [17, 6, 27, 16], 'css_selector .element']
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Skipping stack frames in the error output
|
|
359
|
+
|
|
360
|
+
If you would like to override the `screenshot` method or for some other reason would like to skip stack
|
|
361
|
+
frames when reporting image differences, you can use the `skip_stack_frames` option:
|
|
362
|
+
|
|
363
|
+
```ruby
|
|
364
|
+
test 'test visiting the index' do
|
|
365
|
+
visit root_path
|
|
366
|
+
screenshot :index
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
private
|
|
370
|
+
|
|
371
|
+
def screenshot(name, **options)
|
|
372
|
+
super(name, skip_stack_frames: 1, **options)
|
|
373
|
+
end
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Screenshot Format
|
|
377
|
+
|
|
378
|
+
You can specify the format of the screenshots taken by setting the `screenshot_format` option. By default, the format is set to `"png"`. However, you can change this to any format supported by your image processing driver. For example, to set the format to `"webp"`, you can do the following:
|
|
379
|
+
|
|
380
|
+
```ruby
|
|
381
|
+
Capybara::Screenshot.screenshot_format = "webp"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Customize Capybara#screenshot options
|
|
385
|
+
|
|
386
|
+
Allow to bypass screenshot options to Capybara driver.
|
|
387
|
+
|
|
388
|
+
```ruby
|
|
389
|
+
# To create full page screenshots for Selenium
|
|
390
|
+
Capybara::Screenshot.capybara_screenshot_options[:full_page] = true
|
|
391
|
+
|
|
392
|
+
screenshot('index', median_filter_window_size: 2, capybara_screenshot_options: {full_page: false})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
[← Back to README](../README.md)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Docker Testing
|
|
2
|
+
|
|
3
|
+
## Running tests in Docker
|
|
4
|
+
|
|
5
|
+
Screenshot tests depend on exact browser rendering, which varies across OS and browser versions. Use `bin/dtest` to run tests inside Docker for consistent, reproducible results matching CI:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bin/dtest # Run all tests with all drivers
|
|
9
|
+
bin/dtest test/integration/ # Run specific test directory
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
This builds a Docker image with Chrome and runs the test suite against three Capybara drivers: `cuprite`, `selenium_chrome_headless`, and `selenium_headless`.
|
|
13
|
+
|
|
14
|
+
## Recording baseline screenshots
|
|
15
|
+
|
|
16
|
+
Screenshot baselines are committed to the repo and compared against during tests. When you set up the project for the first time, or after upgrading the browser/driver, you need to re-record them:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
RECORD_SCREENSHOTS=1 bin/dtest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This skips screenshot comparisons and saves new baselines instead. Without this step, tests will fail because your local browser renders pixels differently from the previously committed baselines.
|
|
23
|
+
|
|
24
|
+
[← Back to README](../README.md)
|
data/docs/drivers.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Image Processing Drivers
|
|
2
|
+
|
|
3
|
+
## Perceptual color comparison (VIPS only)
|
|
4
|
+
|
|
5
|
+
By default, color differences are measured using raw RGB channel distance. This can produce
|
|
6
|
+
false positives from anti-aliasing and sub-pixel font rendering — the same page rendered on
|
|
7
|
+
different OS versions or browsers will have slightly different pixel values at text edges.
|
|
8
|
+
|
|
9
|
+
The `perceptual_threshold` option uses the CIE dE00 formula instead, which measures color
|
|
10
|
+
difference the way human eyes perceive it. Anti-aliasing artifacts typically score below 2.0
|
|
11
|
+
on the dE00 scale and are automatically ignored.
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
# Per-screenshot: ignore anti-aliasing, catch real visual changes
|
|
15
|
+
screenshot 'dashboard', perceptual_threshold: 2.0
|
|
16
|
+
|
|
17
|
+
# Global: apply to all screenshots
|
|
18
|
+
Capybara::Screenshot::Diff.perceptual_threshold = 2.0
|
|
19
|
+
|
|
20
|
+
# dE00 scale reference:
|
|
21
|
+
# < 1.0 — not perceptible by human eyes
|
|
22
|
+
# 1-2 — perceptible through close observation (anti-aliasing, font hinting)
|
|
23
|
+
# 2-10 — perceptible at a glance (color shifts, layout changes)
|
|
24
|
+
# > 10 — clearly different colors
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use `perceptual_threshold` when you see false positives from font rendering differences across
|
|
28
|
+
CI environments, or when `color_distance_limit` with raw RGB requires frequent tuning.
|
|
29
|
+
|
|
30
|
+
**⚠️ Important:** `perceptual_threshold` and `color_distance_limit` are **mutually exclusive**.
|
|
31
|
+
If you set both, `perceptual_threshold` takes priority and `color_distance_limit` is silently ignored.
|
|
32
|
+
|
|
33
|
+
These options use different scales and algorithms:
|
|
34
|
+
- `perceptual_threshold` → CIE dE00 perceptual distance (0-100+)
|
|
35
|
+
- `color_distance_limit` → Euclidean RGBA distance (0-510)
|
|
36
|
+
|
|
37
|
+
**Choose one based on your driver setup:**
|
|
38
|
+
- VIPS with `ruby-vips` gem → prefer `perceptual_threshold`
|
|
39
|
+
- ChunkyPNG (no native dependencies) → use `color_distance_limit`
|
|
40
|
+
|
|
41
|
+
## Available Image Processing Drivers
|
|
42
|
+
|
|
43
|
+
There are several image processing supported by this gem.
|
|
44
|
+
There are several options to setup active driver: `:auto`, `:chunky_png` and `:vips`.
|
|
45
|
+
|
|
46
|
+
* `:auto` - will try to load `:vips` if there is gem `ruby-vips`, in other cases will load `:chunky_png`
|
|
47
|
+
* `:chunky_png` and `:vips` will load correspondent driver
|
|
48
|
+
|
|
49
|
+
## Enable VIPS image processing
|
|
50
|
+
|
|
51
|
+
[Vips](https://www.rubydoc.info/gems/ruby-vips/Vips/Image) driver provides a faster comparison,
|
|
52
|
+
and could be enabled by adding `ruby-vips` to `Gemfile`.
|
|
53
|
+
|
|
54
|
+
If need to setup explicitly Vips driver, there are several ways to do this:
|
|
55
|
+
|
|
56
|
+
* Globally: `Capybara::Screenshot::Diff.driver = :vips`
|
|
57
|
+
* Per screenshot option: `screenshot 'index', driver: :vips`
|
|
58
|
+
|
|
59
|
+
With enabled VIPS there are new alternatives to process differences, which are easier to find and support.
|
|
60
|
+
For example, `shift_distance_limit` is a very heavy operation. Instead, use `median_filter_window_size`.
|
|
61
|
+
|
|
62
|
+
## Tolerance level (vips only)
|
|
63
|
+
|
|
64
|
+
You can set a "tolerance" anywhere from 0% to 100%. This is the amount of change that's allowable.
|
|
65
|
+
If the screenshot has changed by more than that amount, it'll flag it as a failure.
|
|
66
|
+
|
|
67
|
+
This is alternative to "Allowed difference size", only the difference that area calculates including valid pixels.
|
|
68
|
+
But "tolerance" compares only different pixels.
|
|
69
|
+
|
|
70
|
+
You can use the `tolerance` option to the `screenshot` method to set level:
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
test 'unstable area' do
|
|
74
|
+
visit '/'
|
|
75
|
+
# tolerance: 0.01 allows 1% of pixels to differ (use for noisy pages)
|
|
76
|
+
screenshot 'index', tolerance: 0.01
|
|
77
|
+
end
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
You can also set this globally:
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
# Default for VIPS is 0.001 (0.1% pixel difference allowed)
|
|
84
|
+
Capybara::Screenshot::Diff.tolerance = 0.001
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Median filter size (vips only)
|
|
88
|
+
|
|
89
|
+
This is an alternative to "Allowed shift distance", but much faster.
|
|
90
|
+
You can find more about this strategy on [Median Filter](https://en.wikipedia.org/wiki/Median_filter).
|
|
91
|
+
Think about this like smoothing of the image, before comparison.
|
|
92
|
+
|
|
93
|
+
You can use the `median_filter_window_size` option to the `screenshot` method to set level:
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
test 'unstable area' do
|
|
97
|
+
visit '/'
|
|
98
|
+
screenshot 'index', median_filter_window_size: 2
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
[← Back to README](../README.md)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Framework Setup
|
|
2
|
+
|
|
3
|
+
## Including DSL
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
There are different modules for different testing frameworks integrations.
|
|
8
|
+
|
|
9
|
+
## Minitest
|
|
10
|
+
|
|
11
|
+
For Minitest, need to require `capybara_screenshot_diff/minitest`.
|
|
12
|
+
In your test class, include the `CapybaraScreenshotDiff::Minitest::Assertions` module:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
require 'capybara_screenshot_diff/minitest'
|
|
16
|
+
|
|
17
|
+
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
|
18
|
+
# Make the Capybara & Capybara Screenshot Diff DSLs available in tests
|
|
19
|
+
include CapybaraScreenshotDiff::DSL
|
|
20
|
+
# Make `assert_*` methods behave like Minitest assertions
|
|
21
|
+
include CapybaraScreenshotDiff::Minitest::Assertions
|
|
22
|
+
|
|
23
|
+
def test_my_feature
|
|
24
|
+
visit '/'
|
|
25
|
+
assert_matches_screenshot 'index'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## RSpec
|
|
31
|
+
|
|
32
|
+
To use the screenshot capturing and change detection features in your tests,
|
|
33
|
+
include the `CapybaraScreenshotDiff::DSL` in your test classes.
|
|
34
|
+
It adds `match_screenshot` matcher to RSpec.
|
|
35
|
+
|
|
36
|
+
> **Important**:
|
|
37
|
+
> The `CapybaraScreenshotDiff::DSL` is automatically included in all feature and system tests by default.
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
require 'capybara_screenshot_diff/rspec'
|
|
42
|
+
|
|
43
|
+
describe 'Permissions admin', type: :feature do
|
|
44
|
+
it 'works with permissions' do
|
|
45
|
+
visit('/')
|
|
46
|
+
expect(page).to match_screenshot('home_page')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
describe 'Permissions admin', type: :non_feature do
|
|
52
|
+
include CapybaraScreenshotDiff::DSL
|
|
53
|
+
|
|
54
|
+
it 'works with permissions' do
|
|
55
|
+
visit('/')
|
|
56
|
+
expect(page).to match_screenshot('home_page')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Cucumber
|
|
62
|
+
|
|
63
|
+
Load Cucumber support by adding the following line (typically to your `features/support/env.rb` file):
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
require 'capybara_screenshot_diff/cucumber'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
And in the steps you can use:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
Then('I should not see any visual difference') do
|
|
73
|
+
screenshot 'homepage'
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Custom Test Frameworks
|
|
78
|
+
|
|
79
|
+
Minitest, RSpec, and Cucumber are supported out of the box. For other frameworks, call `finalize_reporters!` in your framework's "after suite" hook:
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
CapybaraScreenshotDiff.finalize_reporters!
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This generates the HTML report and prints the summary.
|
|
86
|
+
|
|
87
|
+
[← Back to README](../README.md)
|
|
Binary file
|
|
Binary file
|