capybara-screenshot-diff 1.5.5 → 1.6.0
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/.github/workflows/lint.yml +25 -0
- data/.github/workflows/test.yml +13 -27
- data/.standard.yml +3 -2
- data/README.md +19 -11
- data/bin/bundle +114 -0
- data/bin/rake +27 -0
- data/lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb +4 -2
- data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +4 -2
- data/lib/capybara/screenshot/diff/image_compare.rb +14 -10
- data/lib/capybara/screenshot/diff/stabilization.rb +27 -10
- data/lib/capybara/screenshot/diff/test_methods.rb +10 -18
- data/lib/capybara/screenshot/diff/version.rb +1 -1
- data/lib/capybara/screenshot/diff.rb +14 -1
- metadata +6 -4
- data/matrix_test.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e85ce13b84f6e2123eb3ca30dd761437bb1a3d9e06bc7c6ae2ae7baeedab7c2c
|
4
|
+
data.tar.gz: 9583c84bb295c48ab0b7fe262fccdf1e5f4edd27c551a98722e3951fcc8e0134
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3aeb660f1307065ac2147153878dbbbb68441c33c34c4fb2e288e227d6abad5714c3a94f7cc0934acddfc02c3c36610b06a3652a5c5b8df21c1f3a60049c1db
|
7
|
+
data.tar.gz: 17fda8ceb42ed9be84a7548f02bfe8940385a6abd6e8e185c2f9753f8c252c577bcafeea576a1b311e85dfb144825916b51db654d7eebadfa8d17f1231ddbcd5
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Ruby Linter
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
paths:
|
6
|
+
- '*.rb'
|
7
|
+
- '!bin/**'
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
lint:
|
11
|
+
name: Lint
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- name: Checkout code
|
16
|
+
uses: actions/checkout@v2
|
17
|
+
|
18
|
+
- name: Set up Ruby
|
19
|
+
uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: '3.1'
|
22
|
+
bundler-cache: true
|
23
|
+
|
24
|
+
- name: Run Standard Ruby linter
|
25
|
+
run: bin/standardrb --no-fix --fail-fast
|
data/.github/workflows/test.yml
CHANGED
@@ -3,9 +3,11 @@ name: Test
|
|
3
3
|
on:
|
4
4
|
push:
|
5
5
|
branches: [ master ]
|
6
|
-
pull_request_target:
|
7
|
-
branches: [ master ]
|
8
6
|
pull_request:
|
7
|
+
paths:
|
8
|
+
- '*.rb'
|
9
|
+
- '*.gemfile'
|
10
|
+
- '!bin/**'
|
9
11
|
|
10
12
|
env:
|
11
13
|
BUNDLE_GEMFILE: 'gemfiles/rails70_gems.rb'
|
@@ -13,23 +15,6 @@ env:
|
|
13
15
|
WD_CACHE_TIME: '864000' # 10 days
|
14
16
|
|
15
17
|
jobs:
|
16
|
-
lint:
|
17
|
-
name: Lint
|
18
|
-
runs-on: ubuntu-latest
|
19
|
-
|
20
|
-
steps:
|
21
|
-
- name: Checkout code
|
22
|
-
uses: actions/checkout@v2
|
23
|
-
|
24
|
-
- name: Set up Ruby
|
25
|
-
uses: ruby/setup-ruby@v1
|
26
|
-
with:
|
27
|
-
ruby-version: '3.0'
|
28
|
-
bundler-cache: true
|
29
|
-
|
30
|
-
- name: Run Standard Ruby linter
|
31
|
-
run: bin/standardrb --no-fix --fail-fast
|
32
|
-
|
33
18
|
test:
|
34
19
|
name: Functional Testing
|
35
20
|
runs-on: ubuntu-20.04 # In order to install libvips 8.9+ version
|
@@ -65,8 +50,8 @@ jobs:
|
|
65
50
|
path: coverage
|
66
51
|
|
67
52
|
matrix:
|
68
|
-
name: Test Integration
|
69
|
-
needs: [ 'test'
|
53
|
+
name: Test Integration Rails & Ruby
|
54
|
+
needs: [ 'test' ]
|
70
55
|
runs-on: ubuntu-20.04
|
71
56
|
|
72
57
|
strategy:
|
@@ -79,9 +64,10 @@ jobs:
|
|
79
64
|
include:
|
80
65
|
- ruby-version: 2.7
|
81
66
|
gemfile: rails70_gems.rb
|
82
|
-
|
83
|
-
|
84
|
-
|
67
|
+
- ruby-version: 3.0
|
68
|
+
gemfile: rails70_gems.rb
|
69
|
+
- ruby-version: 3.1
|
70
|
+
gemfile: rails70_gems.rb
|
85
71
|
env:
|
86
72
|
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}
|
87
73
|
|
@@ -102,8 +88,8 @@ jobs:
|
|
102
88
|
run: bundle exec rake test
|
103
89
|
|
104
90
|
matrix_screenshot_driver:
|
105
|
-
name: Test Integration
|
106
|
-
needs: [ 'test'
|
91
|
+
name: Test Integration Capybara & Image Drivers
|
92
|
+
needs: [ 'test' ]
|
107
93
|
runs-on: ubuntu-20.04
|
108
94
|
|
109
95
|
strategy:
|
@@ -121,7 +107,7 @@ jobs:
|
|
121
107
|
- name: Set up Ruby
|
122
108
|
uses: ruby/setup-ruby@v1
|
123
109
|
with:
|
124
|
-
ruby-version: '3.
|
110
|
+
ruby-version: '3.1'
|
125
111
|
bundler-cache: true
|
126
112
|
|
127
113
|
- name: Install libvips
|
data/.standard.yml
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
fix: true # default: false
|
2
2
|
parallel: true # default: false
|
3
3
|
format: progress # default: Standard::Formatter
|
4
|
-
ruby_version: 2.
|
4
|
+
ruby_version: 2.7 # default: RUBY_VERSION
|
5
5
|
default_ignores: false # default: true
|
6
6
|
|
7
7
|
ignore: # default: []
|
8
|
+
- 'bin/**/*'
|
9
|
+
- 'gemfiles/vendor/**/*'
|
8
10
|
- 'gemfiles/**/*':
|
9
11
|
- Security/Eval
|
10
|
-
- 'gemfiles/vendor/**/*'
|
11
12
|
- 'vendor/**/*'
|
data/README.md
CHANGED
@@ -38,16 +38,7 @@ Or install it yourself as:
|
|
38
38
|
In your test class, include the `Capybara::Screenshot::Diff` module:
|
39
39
|
|
40
40
|
```ruby
|
41
|
-
class
|
42
|
-
include Capybara::Screenshot::Diff
|
43
|
-
...
|
44
|
-
end
|
45
|
-
```
|
46
|
-
|
47
|
-
or if you use the integration test directly:
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
class ActionDispatch::IntegrationTest
|
41
|
+
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
51
42
|
include Capybara::Screenshot::Diff
|
52
43
|
...
|
53
44
|
end
|
@@ -196,6 +187,23 @@ test.
|
|
196
187
|
|
197
188
|
|
198
189
|
|
190
|
+
### Capturing one area instead of the whole page
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
test 'the cool' do
|
194
|
+
visit '/feature'
|
195
|
+
screenshot 'cool_element', crop: bounds('#my_element')
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
def bounds(selector)
|
201
|
+
element = evaluate_script("document.querySelector('#{selector}').getBoundingClientRect()")
|
202
|
+
[element['left'], element['top'], element['right'], element['bottom']]
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
|
199
207
|
### Multiple Capybara drivers
|
200
208
|
|
201
209
|
Often it is useful to test your app using different browsers. To avoid the
|
@@ -350,7 +358,7 @@ test 'max wait time' do
|
|
350
358
|
end
|
351
359
|
```
|
352
360
|
|
353
|
-
###
|
361
|
+
### Hiding the caret for active input elements
|
354
362
|
|
355
363
|
In Chrome the screenshot includes the blinking input cursor. This can make it impossible to get a
|
356
364
|
stable screenshot. To get around this you can set the `hide caret` option:
|
data/bin/bundle
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../gems.rb", __dir__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_requirement
|
64
|
+
@bundler_requirement ||=
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
bundler_requirement_for(lockfile_version)
|
67
|
+
end
|
68
|
+
|
69
|
+
def bundler_requirement_for(version)
|
70
|
+
return "#{Gem::Requirement.default}.a" unless version
|
71
|
+
|
72
|
+
bundler_gem_version = Gem::Version.new(version)
|
73
|
+
|
74
|
+
requirement = bundler_gem_version.approximate_recommendation
|
75
|
+
|
76
|
+
return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
|
77
|
+
|
78
|
+
requirement += ".a" if bundler_gem_version.prerelease?
|
79
|
+
|
80
|
+
requirement
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_bundler!
|
84
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
85
|
+
|
86
|
+
activate_bundler
|
87
|
+
end
|
88
|
+
|
89
|
+
def activate_bundler
|
90
|
+
gem_error = activation_error_handling do
|
91
|
+
gem "bundler", bundler_requirement
|
92
|
+
end
|
93
|
+
return if gem_error.nil?
|
94
|
+
require_error = activation_error_handling do
|
95
|
+
require "bundler/version"
|
96
|
+
end
|
97
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
98
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
99
|
+
exit 42
|
100
|
+
end
|
101
|
+
|
102
|
+
def activation_error_handling
|
103
|
+
yield
|
104
|
+
nil
|
105
|
+
rescue StandardError, LoadError => e
|
106
|
+
e
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
m.load_bundler!
|
111
|
+
|
112
|
+
if m.invoked_as_script?
|
113
|
+
load Gem.bin_path("bundler", "bundle")
|
114
|
+
end
|
data/bin/rake
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../gems.rb", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("rake", "rake")
|
@@ -13,9 +13,11 @@ module Capybara
|
|
13
13
|
|
14
14
|
attr_reader :new_file_name, :old_file_name
|
15
15
|
|
16
|
-
def initialize(new_file_name, old_file_name = nil,
|
16
|
+
def initialize(new_file_name, old_file_name = nil, options = {})
|
17
|
+
options = old_file_name if old_file_name.is_a?(Hash)
|
18
|
+
|
17
19
|
@new_file_name = new_file_name
|
18
|
-
@old_file_name = old_file_name || "#{new_file_name}
|
20
|
+
@old_file_name = old_file_name || "#{new_file_name}#{ImageCompare::TMP_FILE_SUFFIX}"
|
19
21
|
|
20
22
|
@color_distance_limit = options[:color_distance_limit]
|
21
23
|
@shift_distance_limit = options[:shift_distance_limit]
|
@@ -18,9 +18,11 @@ module Capybara
|
|
18
18
|
class VipsDriver
|
19
19
|
attr_reader :new_file_name, :old_file_name, :options
|
20
20
|
|
21
|
-
def initialize(new_file_name, old_file_name = nil,
|
21
|
+
def initialize(new_file_name, old_file_name = nil, options = {})
|
22
|
+
options = old_file_name if old_file_name.is_a?(Hash)
|
23
|
+
|
22
24
|
@new_file_name = new_file_name
|
23
|
-
@old_file_name = old_file_name || "#{new_file_name}
|
25
|
+
@old_file_name = old_file_name || "#{new_file_name}#{ImageCompare::TMP_FILE_SUFFIX}"
|
24
26
|
|
25
27
|
@options = options || {}
|
26
28
|
|
@@ -8,27 +8,31 @@ module Capybara
|
|
8
8
|
# Compare two images and determine if they are equal, different, or within some comparison
|
9
9
|
# range considering color values and difference area size.
|
10
10
|
class ImageCompare < SimpleDelegator
|
11
|
+
TMP_FILE_SUFFIX = "~"
|
12
|
+
|
11
13
|
attr_reader :driver, :driver_options
|
12
14
|
|
13
15
|
attr_reader :annotated_new_file_name, :annotated_old_file_name, :area_size_limit,
|
14
16
|
:color_distance_limit, :new_file_name, :old_file_name, :shift_distance_limit,
|
15
17
|
:skip_area
|
16
18
|
|
17
|
-
def initialize(new_file_name, old_file_name = nil,
|
19
|
+
def initialize(new_file_name, old_file_name = nil, options = {})
|
20
|
+
options = old_file_name if old_file_name.is_a?(Hash)
|
21
|
+
|
18
22
|
@new_file_name = new_file_name
|
19
|
-
@old_file_name = old_file_name || "#{new_file_name}
|
23
|
+
@old_file_name = old_file_name || "#{new_file_name}#{ImageCompare::TMP_FILE_SUFFIX}"
|
20
24
|
@annotated_old_file_name = "#{new_file_name.chomp(".png")}.committed.png"
|
21
25
|
@annotated_new_file_name = "#{new_file_name.chomp(".png")}.latest.png"
|
22
26
|
|
23
|
-
@driver_options =
|
27
|
+
@driver_options = options
|
24
28
|
|
25
|
-
@color_distance_limit =
|
26
|
-
@area_size_limit =
|
27
|
-
@shift_distance_limit =
|
28
|
-
@dimensions =
|
29
|
-
@skip_area =
|
30
|
-
@tolerance =
|
31
|
-
@median_filter_window_size =
|
29
|
+
@color_distance_limit = options[:color_distance_limit] || 0
|
30
|
+
@area_size_limit = options[:area_size_limit]
|
31
|
+
@shift_distance_limit = options[:shift_distance_limit]
|
32
|
+
@dimensions = options[:dimensions]
|
33
|
+
@skip_area = options[:skip_area]
|
34
|
+
@tolerance = options[:tolerance]
|
35
|
+
@median_filter_window_size = options[:median_filter_window_size]
|
32
36
|
|
33
37
|
driver_klass = find_driver_class_for(@driver_options.fetch(:driver, :chunky_png))
|
34
38
|
@driver = driver_klass.new(@new_file_name, @old_file_name, **@driver_options)
|
@@ -30,13 +30,13 @@ module Capybara
|
|
30
30
|
}
|
31
31
|
JS
|
32
32
|
|
33
|
-
def take_stable_screenshot(comparison, stability_time_limit:, wait:)
|
33
|
+
def take_stable_screenshot(comparison, stability_time_limit:, wait:, crop:)
|
34
34
|
previous_file_name = comparison.old_file_name
|
35
35
|
screenshot_started_at = last_image_change_at = Time.now
|
36
36
|
clean_stabilization_images(comparison.new_file_name)
|
37
37
|
|
38
38
|
1.step do |i|
|
39
|
-
take_right_size_screenshot(comparison)
|
39
|
+
take_right_size_screenshot(comparison, crop: crop)
|
40
40
|
if comparison.quick_equal?
|
41
41
|
clean_stabilization_images(comparison.new_file_name)
|
42
42
|
break
|
@@ -60,10 +60,14 @@ module Capybara
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
previous_file_name =
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
previous_file_name = build_snapshot_version_file_name(
|
64
|
+
comparison,
|
65
|
+
i,
|
66
|
+
screenshot_started_at,
|
67
|
+
stabilization_comparison
|
68
|
+
)
|
69
|
+
|
70
|
+
FileUtils.mv(comparison.new_file_name, previous_file_name)
|
67
71
|
|
68
72
|
check_max_wait_time(
|
69
73
|
comparison,
|
@@ -83,8 +87,15 @@ module Capybara
|
|
83
87
|
|
84
88
|
private
|
85
89
|
|
90
|
+
def build_snapshot_version_file_name(comparison, iteration, screenshot_started_at, stabilization_comparison)
|
91
|
+
"#{comparison.new_file_name.chomp(".png")}" \
|
92
|
+
"_x#{format("%02i", iteration)}_#{(Time.now - screenshot_started_at).round(1)}s" \
|
93
|
+
"_#{stabilization_comparison.difference_region&.to_s&.gsub(", ", "_") || :initial}.png" \
|
94
|
+
"#{ImageCompare::TMP_FILE_SUFFIX}"
|
95
|
+
end
|
96
|
+
|
86
97
|
def make_stabilization_comparison_from(comparison, new_file_name, previous_file_name)
|
87
|
-
ImageCompare.new(new_file_name, previous_file_name,
|
98
|
+
ImageCompare.new(new_file_name, previous_file_name, comparison.driver_options)
|
88
99
|
end
|
89
100
|
|
90
101
|
def reduce_retina_image_size(file_name, driver)
|
@@ -107,7 +118,7 @@ module Capybara
|
|
107
118
|
end
|
108
119
|
|
109
120
|
def stabilization_images(base_file)
|
110
|
-
Dir["#{base_file.chomp(".png")}_x*.png
|
121
|
+
Dir["#{base_file.chomp(".png")}_x*.png#{ImageCompare::TMP_FILE_SUFFIX}"].sort
|
111
122
|
end
|
112
123
|
|
113
124
|
def clean_stabilization_images(base_file)
|
@@ -119,7 +130,7 @@ module Capybara
|
|
119
130
|
if Capybara::Screenshot.blur_active_element
|
120
131
|
active_element = execute_script(<<-JS)
|
121
132
|
ae = document.activeElement;
|
122
|
-
if (ae.nodeName
|
133
|
+
if (ae.nodeName === "INPUT" || ae.nodeName === "TEXTAREA") {
|
123
134
|
ae.blur();
|
124
135
|
return ae;
|
125
136
|
}
|
@@ -131,12 +142,18 @@ module Capybara
|
|
131
142
|
blurred_input
|
132
143
|
end
|
133
144
|
|
134
|
-
def take_right_size_screenshot(comparison)
|
145
|
+
def take_right_size_screenshot(comparison, crop:)
|
135
146
|
save_screenshot(comparison.new_file_name)
|
136
147
|
|
137
148
|
# TODO(uwe): Remove when chromedriver takes right size screenshots
|
138
149
|
reduce_retina_image_size(comparison.new_file_name, comparison.driver)
|
139
150
|
# ODOT
|
151
|
+
|
152
|
+
if crop
|
153
|
+
full_img = comparison.driver.from_file(comparison.new_file_name)
|
154
|
+
area_img = full_img.crop(crop[0], crop[1], crop[2] - crop[0], crop[3] - crop[1])
|
155
|
+
comparison.driver.save_image_to(area_img, comparison.new_file_name)
|
156
|
+
end
|
140
157
|
end
|
141
158
|
|
142
159
|
def check_max_wait_time(comparison, screenshot_started_at, max_wait_time:)
|
@@ -61,24 +61,16 @@ module Capybara
|
|
61
61
|
FileUtils.rm_rf screenshot_dir
|
62
62
|
end
|
63
63
|
|
64
|
-
# @return [Boolean]
|
65
|
-
def screenshot(
|
66
|
-
name,
|
67
|
-
stability_time_limit: Screenshot.stability_time_limit,
|
68
|
-
wait: Capybara.default_max_wait_time,
|
69
|
-
**driver_options
|
70
|
-
)
|
64
|
+
# @return [Boolean] whether a screenshot was taken
|
65
|
+
def screenshot(name, options = {})
|
71
66
|
return false unless Screenshot.active?
|
72
67
|
return false if window_size_is_wrong?
|
73
68
|
|
74
|
-
driver_options =
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
skip_area: Diff.skip_area,
|
80
|
-
tolerance: Diff.tolerance
|
81
|
-
}.merge(driver_options)
|
69
|
+
driver_options = Diff.default_options.merge(options)
|
70
|
+
|
71
|
+
stability_time_limit = driver_options[:stability_time_limit]
|
72
|
+
wait = driver_options[:wait]
|
73
|
+
crop = driver_options.delete(:crop)
|
82
74
|
|
83
75
|
# Allow nil or single or multiple areas
|
84
76
|
if driver_options[:skip_area]
|
@@ -93,14 +85,14 @@ module Capybara
|
|
93
85
|
file_name = "#{Screenshot.screenshot_area_abs}/#{name}.png"
|
94
86
|
|
95
87
|
FileUtils.mkdir_p File.dirname(file_name)
|
96
|
-
comparison = ImageCompare.new(file_name,
|
88
|
+
comparison = ImageCompare.new(file_name, nil, driver_options)
|
97
89
|
checkout_vcs(name, comparison)
|
98
90
|
begin
|
99
91
|
blurred_input = prepare_page_for_screenshot(timeout: wait)
|
100
92
|
if stability_time_limit
|
101
|
-
take_stable_screenshot(comparison, stability_time_limit: stability_time_limit, wait: wait)
|
93
|
+
take_stable_screenshot(comparison, stability_time_limit: stability_time_limit, wait: wait, crop: crop)
|
102
94
|
else
|
103
|
-
take_right_size_screenshot(comparison)
|
95
|
+
take_right_size_screenshot(comparison, crop: crop)
|
104
96
|
end
|
105
97
|
ensure
|
106
98
|
blurred_input&.click
|
@@ -62,6 +62,19 @@ module Capybara
|
|
62
62
|
ASSERTION = RuntimeError
|
63
63
|
end
|
64
64
|
|
65
|
+
def self.default_options
|
66
|
+
{
|
67
|
+
area_size_limit: area_size_limit,
|
68
|
+
color_distance_limit: color_distance_limit,
|
69
|
+
driver: driver,
|
70
|
+
shift_distance_limit: shift_distance_limit,
|
71
|
+
skip_area: skip_area,
|
72
|
+
stability_time_limit: Screenshot.stability_time_limit,
|
73
|
+
tolerance: tolerance,
|
74
|
+
wait: Capybara.default_max_wait_time
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
65
78
|
def self.included(klass)
|
66
79
|
klass.include TestMethods
|
67
80
|
klass.setup do
|
@@ -75,7 +88,7 @@ module Capybara
|
|
75
88
|
end
|
76
89
|
|
77
90
|
klass.teardown do
|
78
|
-
if Capybara::Screenshot
|
91
|
+
if Capybara::Screenshot.active? && @test_screenshots
|
79
92
|
test_screenshot_errors = @test_screenshots
|
80
93
|
.map { |caller, name, compare| assert_image_not_changed(caller, name, compare) }
|
81
94
|
@test_screenshots = nil # release the comparison objects from memory
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara-screenshot-diff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uwe Kubosch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -72,6 +72,7 @@ extensions: []
|
|
72
72
|
extra_rdoc_files: []
|
73
73
|
files:
|
74
74
|
- ".gitattributes"
|
75
|
+
- ".github/workflows/lint.yml"
|
75
76
|
- ".github/workflows/test.yml"
|
76
77
|
- ".gitignore"
|
77
78
|
- ".standard.yml"
|
@@ -80,8 +81,10 @@ files:
|
|
80
81
|
- LICENSE.txt
|
81
82
|
- README.md
|
82
83
|
- Rakefile
|
84
|
+
- bin/bundle
|
83
85
|
- bin/console
|
84
86
|
- bin/install-vips
|
87
|
+
- bin/rake
|
85
88
|
- bin/setup
|
86
89
|
- bin/standardrb
|
87
90
|
- capybara-screenshot-diff.gemspec
|
@@ -101,7 +104,6 @@ files:
|
|
101
104
|
- lib/capybara/screenshot/diff/test_methods.rb
|
102
105
|
- lib/capybara/screenshot/diff/vcs.rb
|
103
106
|
- lib/capybara/screenshot/diff/version.rb
|
104
|
-
- matrix_test.rb
|
105
107
|
- tmp/.keep
|
106
108
|
homepage: https://github.com/donv/capybara-screenshot-diff
|
107
109
|
licenses:
|
@@ -123,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
125
|
- !ruby/object:Gem::Version
|
124
126
|
version: '0'
|
125
127
|
requirements: []
|
126
|
-
rubygems_version: 3.3.
|
128
|
+
rubygems_version: 3.3.7
|
127
129
|
signing_key:
|
128
130
|
specification_version: 4
|
129
131
|
summary: Track your GUI changes with diff assertions
|
data/matrix_test.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -w
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
update_gemfiles = ARGV.delete("--update")
|
5
|
-
|
6
|
-
require "yaml"
|
7
|
-
travis = YAML.safe_load(File.read(".travis.yml"))
|
8
|
-
|
9
|
-
def run_script(ruby, env, gemfile)
|
10
|
-
env.scan(/\b(?<key>[A-Z_]+)="(?<value>.+?)"/) do |key, value|
|
11
|
-
ENV[key] = value
|
12
|
-
end
|
13
|
-
puts "*" * 80
|
14
|
-
puts "Testing #{ruby} #{gemfile} #{env}"
|
15
|
-
puts
|
16
|
-
system("chruby-exec #{ruby} -- bundle exec rake") || exit(1)
|
17
|
-
puts "Testing #{ruby} #{gemfile} OK"
|
18
|
-
puts "*" * 80
|
19
|
-
end
|
20
|
-
|
21
|
-
def use_gemfile(ruby, gemfile, update_gemfiles)
|
22
|
-
puts "$" * 80
|
23
|
-
ENV["BUNDLE_GEMFILE"] = gemfile
|
24
|
-
|
25
|
-
bundler_version = `grep -A1 "BUNDLED WITH" #{gemfile}.lock | tail -n 1`
|
26
|
-
bundler_version = "~> 2.0" if bundler_version.strip.empty?
|
27
|
-
|
28
|
-
version_arg = "-v '#{bundler_version}'"
|
29
|
-
bundler_gem_check_cmd = "chruby-exec #{ruby} -- gem query -i -n bundler #{version_arg} >/dev/null"
|
30
|
-
system "#{bundler_gem_check_cmd} || chruby-exec #{ruby} -- gem install #{version_arg} bundler" || exit(1)
|
31
|
-
|
32
|
-
if update_gemfiles
|
33
|
-
system "chruby-exec #{ruby} -- bundle update"
|
34
|
-
else
|
35
|
-
system "chruby-exec #{ruby} -- bundle check >/dev/null || chruby-exec #{ruby} -- bundle install"
|
36
|
-
end || exit(1)
|
37
|
-
yield
|
38
|
-
puts "$" * 80
|
39
|
-
end
|
40
|
-
|
41
|
-
travis["rvm"].each do |ruby|
|
42
|
-
next if /head/.match?(ruby) # ruby-install does not support HEAD installation
|
43
|
-
|
44
|
-
puts "#" * 80
|
45
|
-
puts "Testing #{ruby}"
|
46
|
-
puts
|
47
|
-
system "ruby-install --no-reinstall #{ruby}" || exit(1)
|
48
|
-
travis["gemfile"].each do |gemfile|
|
49
|
-
if travis["matrix"] &&
|
50
|
-
(travis["matrix"]["exclude"].to_a + travis["matrix"]["allow_failures"].to_a)
|
51
|
-
.any? { |f| f["rvm"] == ruby && (f["gemfile"].nil? || f["gemfile"] == gemfile) }
|
52
|
-
puts "Skipping known failure."
|
53
|
-
next
|
54
|
-
end
|
55
|
-
use_gemfile(ruby, gemfile, update_gemfiles) do
|
56
|
-
travis["env"].each do |env|
|
57
|
-
run_script(ruby, env, gemfile)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
puts "Testing #{ruby} OK"
|
62
|
-
puts "#" * 80
|
63
|
-
end
|
64
|
-
|
65
|
-
print "\033[0;32m"
|
66
|
-
print " TESTS PASSED OK!"
|
67
|
-
puts "\033[0m"
|