capybara-screenshot-diff 1.5.5 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|