capybara-screenshot-diff 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +29 -0
- data/capybara-screenshot-diff.gemspec +7 -4
- data/gems.rb +8 -2
- data/lib/capybara/screenshot/diff/browser_helpers.rb +29 -28
- data/lib/capybara/screenshot/diff/cucumber.rb +11 -0
- data/lib/capybara/screenshot/diff/difference.rb +63 -0
- data/lib/capybara/screenshot/diff/drivers/base_driver.rb +42 -0
- data/lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb +188 -260
- data/lib/capybara/screenshot/diff/drivers/utils.rb +16 -0
- data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +53 -103
- data/lib/capybara/screenshot/diff/drivers.rb +16 -0
- data/lib/capybara/screenshot/diff/image_compare.rb +125 -154
- data/lib/capybara/screenshot/diff/os.rb +1 -1
- data/lib/capybara/screenshot/diff/screenshot_matcher.rb +128 -0
- data/lib/capybara/screenshot/diff/screenshoter.rb +137 -0
- data/lib/capybara/screenshot/diff/stabilization.rb +0 -184
- data/lib/capybara/screenshot/diff/stable_screenshoter.rb +106 -0
- data/lib/capybara/screenshot/diff/test_methods.rb +51 -90
- data/lib/capybara/screenshot/diff/vcs.rb +44 -22
- data/lib/capybara/screenshot/diff/version.rb +1 -1
- data/lib/capybara/screenshot/diff.rb +13 -17
- data/sig/capybara/screenshot/diff/diff.rbs +28 -0
- data/sig/capybara/screenshot/diff/difference.rbs +33 -0
- data/sig/capybara/screenshot/diff/drivers/base_driver.rbs +63 -0
- data/sig/capybara/screenshot/diff/drivers/browser_helpers.rbs +36 -0
- data/sig/capybara/screenshot/diff/drivers/chunky_png_driver.rbs +89 -0
- data/sig/capybara/screenshot/diff/drivers/utils.rbs +13 -0
- data/sig/capybara/screenshot/diff/drivers/vips_driver.rbs +25 -0
- data/sig/capybara/screenshot/diff/image_compare.rbs +93 -0
- data/sig/capybara/screenshot/diff/os.rbs +11 -0
- data/sig/capybara/screenshot/diff/region.rbs +43 -0
- data/sig/capybara/screenshot/diff/screenshot_matcher.rbs +60 -0
- data/sig/capybara/screenshot/diff/screenshoter.rbs +48 -0
- data/sig/capybara/screenshot/diff/stable_screenshoter.rbs +29 -0
- data/sig/capybara/screenshot/diff/test_methods.rbs +39 -0
- data/sig/capybara/screenshot/diff/vcs.rbs +17 -0
- metadata +36 -27
- data/.gitattributes +0 -4
- data/.github/dependabot.yml +0 -8
- data/.github/workflows/lint.yml +0 -25
- data/.github/workflows/test.yml +0 -138
- data/.gitignore +0 -14
- data/.standard.yml +0 -12
- data/CONTRIBUTING.md +0 -24
- data/Dockerfile +0 -59
- data/README.md +0 -567
- data/bin/bundle +0 -114
- data/bin/console +0 -15
- data/bin/install-vips +0 -11
- data/bin/rake +0 -27
- data/bin/setup +0 -8
- data/bin/standardrb +0 -29
- data/gemfiles/rails60_gems.rb +0 -8
- data/gemfiles/rails61_gems.rb +0 -7
- data/gemfiles/rails70_gems.rb +0 -7
- data/tmp/.keep +0 -0
@@ -5,43 +5,41 @@ require "capybara"
|
|
5
5
|
require "action_controller"
|
6
6
|
require "action_dispatch"
|
7
7
|
require "active_support/core_ext/string/strip"
|
8
|
+
require "pathname"
|
9
|
+
|
10
|
+
require_relative "drivers"
|
8
11
|
require_relative "image_compare"
|
9
|
-
require_relative "stabilization"
|
10
12
|
require_relative "vcs"
|
11
13
|
require_relative "browser_helpers"
|
12
14
|
require_relative "region"
|
13
15
|
|
16
|
+
require_relative "screenshot_matcher"
|
17
|
+
|
14
18
|
# Add the `screenshot` method to ActionDispatch::IntegrationTest
|
15
19
|
module Capybara
|
16
20
|
module Screenshot
|
17
21
|
module Diff
|
18
22
|
module TestMethods
|
19
|
-
include Stabilization
|
20
|
-
include Vcs
|
21
|
-
include BrowserHelpers
|
22
|
-
|
23
23
|
def initialize(*)
|
24
24
|
super
|
25
25
|
@screenshot_counter = nil
|
26
26
|
@screenshot_group = nil
|
27
27
|
@screenshot_section = nil
|
28
28
|
@test_screenshot_errors = nil
|
29
|
-
@test_screenshots =
|
29
|
+
@test_screenshots = []
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
32
|
+
def build_full_name(name)
|
33
|
+
if @screenshot_counter
|
34
|
+
name = format("%02i_#{name}", @screenshot_counter)
|
35
|
+
@screenshot_counter += 1
|
36
|
+
end
|
38
37
|
|
39
|
-
|
40
|
-
File.join group_parts.push(name).map(&:to_s)
|
38
|
+
File.join(*group_parts.push(name.to_s))
|
41
39
|
end
|
42
40
|
|
43
41
|
def screenshot_dir
|
44
|
-
File.join
|
42
|
+
File.join(*([Screenshot.screenshot_area] + group_parts))
|
45
43
|
end
|
46
44
|
|
47
45
|
def screenshot_section(name)
|
@@ -50,104 +48,67 @@ module Capybara
|
|
50
48
|
|
51
49
|
def screenshot_group(name)
|
52
50
|
@screenshot_group = name.to_s
|
53
|
-
@screenshot_counter = 0
|
51
|
+
@screenshot_counter = @screenshot_group.present? ? 0 : nil
|
54
52
|
return unless Screenshot.active? && name.present?
|
55
53
|
|
56
54
|
FileUtils.rm_rf screenshot_dir
|
57
55
|
end
|
58
56
|
|
59
|
-
|
60
|
-
|
61
|
-
return false unless Screenshot.active?
|
62
|
-
return false if window_size_is_wrong?
|
63
|
-
|
64
|
-
driver_options = Diff.default_options.merge(options)
|
65
|
-
|
66
|
-
stability_time_limit = driver_options[:stability_time_limit]
|
67
|
-
wait = driver_options[:wait]
|
68
|
-
crop = calculate_crop_region(driver_options)
|
69
|
-
|
70
|
-
if @screenshot_counter
|
71
|
-
name = "#{format("%02i", @screenshot_counter)}_#{name}"
|
72
|
-
@screenshot_counter += 1
|
73
|
-
end
|
74
|
-
name = full_name(name)
|
75
|
-
file_name = "#{Screenshot.screenshot_area_abs}/#{name}.png"
|
76
|
-
|
77
|
-
create_output_directory_for(file_name)
|
78
|
-
|
79
|
-
comparison = ImageCompare.new(file_name, nil, driver_options)
|
80
|
-
checkout_vcs(name, comparison.old_file_name, comparison.new_file_name)
|
81
|
-
take_screenshot(comparison, crop, stability_time_limit, wait)
|
82
|
-
|
83
|
-
return false unless comparison.old_file_exists?
|
84
|
-
|
85
|
-
# Allow nil or single or multiple areas
|
86
|
-
if driver_options[:skip_area]
|
87
|
-
comparison.skip_area = calculate_skip_area(driver_options[:skip_area], crop)
|
88
|
-
end
|
89
|
-
|
90
|
-
(@test_screenshots ||= []) << [caller[skip_stack_frames], name, comparison]
|
91
|
-
|
57
|
+
def schedule_match_job(job)
|
58
|
+
(@test_screenshots ||= []) << job
|
92
59
|
true
|
93
60
|
end
|
94
61
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
|
62
|
+
def group_parts
|
63
|
+
parts = []
|
64
|
+
parts << @screenshot_section if @screenshot_section.present?
|
65
|
+
parts << @screenshot_group if @screenshot_group.present?
|
66
|
+
parts
|
99
67
|
end
|
100
68
|
|
101
|
-
|
69
|
+
def screenshot(name, skip_stack_frames: 0, **options)
|
70
|
+
return false unless Screenshot.active?
|
102
71
|
|
103
|
-
|
104
|
-
|
105
|
-
return nil unless crop_coordinates
|
72
|
+
screenshot_full_name = build_full_name(name)
|
73
|
+
job = build_screenshot_matches_job(screenshot_full_name, options)
|
106
74
|
|
107
|
-
|
108
|
-
Region.from_edge_coordinates(*crop_coordinates)
|
109
|
-
end
|
75
|
+
return false unless job
|
110
76
|
|
111
|
-
|
112
|
-
FileUtils.mkdir_p File.dirname(file_name)
|
113
|
-
end
|
77
|
+
test_caller = caller(skip_stack_frames)
|
114
78
|
|
115
|
-
|
116
|
-
|
117
|
-
if stability_time_limit
|
118
|
-
take_stable_screenshot(
|
119
|
-
comparison,
|
120
|
-
crop: crop,
|
121
|
-
stability_time_limit: stability_time_limit,
|
122
|
-
wait: wait
|
123
|
-
)
|
79
|
+
if Screenshot::Diff.delayed
|
80
|
+
schedule_match_job([test_caller] + job)
|
124
81
|
else
|
125
|
-
|
82
|
+
error_msg = assert_image_not_changed(job.first, job.last)
|
83
|
+
if error_msg
|
84
|
+
error = ASSERTION.new(error_msg)
|
85
|
+
error.set_backtrace(caller(2))
|
86
|
+
raise error
|
87
|
+
end
|
126
88
|
end
|
127
|
-
ensure
|
128
|
-
blurred_input&.click
|
129
89
|
end
|
130
90
|
|
131
|
-
def
|
132
|
-
|
133
|
-
skip_area = Array(skip_area)
|
134
|
-
|
135
|
-
css_selectors, regions = skip_area.compact.partition { |region| region.is_a? String }
|
91
|
+
def assert_image_not_changed(name, comparison)
|
92
|
+
result = comparison.different?
|
136
93
|
|
137
|
-
|
138
|
-
result
|
139
|
-
|
140
|
-
|
94
|
+
# Cleanup after comparisons
|
95
|
+
if !result && comparison.base_image_path.exist?
|
96
|
+
FileUtils.mv(comparison.base_image_path, comparison.image_path, force: true)
|
97
|
+
else
|
98
|
+
FileUtils.rm_rf(comparison.base_image_path)
|
99
|
+
end
|
141
100
|
|
142
|
-
|
101
|
+
return unless result
|
143
102
|
|
144
|
-
|
103
|
+
"Screenshot does not match for '#{name}' #{comparison.error_message}"
|
145
104
|
end
|
146
105
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
106
|
+
private
|
107
|
+
|
108
|
+
def build_screenshot_matches_job(screenshot_full_name, options)
|
109
|
+
ScreenshotMatcher
|
110
|
+
.new(screenshot_full_name, options)
|
111
|
+
.build_screenshot_matches_job
|
151
112
|
end
|
152
113
|
end
|
153
114
|
end
|
@@ -1,42 +1,64 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "os"
|
4
|
+
|
4
5
|
module Capybara
|
5
6
|
module Screenshot
|
6
7
|
module Diff
|
7
8
|
module Vcs
|
8
9
|
SILENCE_ERRORS = Os::ON_WINDOWS ? "2>nul" : "2>/dev/null"
|
9
10
|
|
10
|
-
def restore_git_revision(
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def self.restore_git_revision(screenshot_path, checkout_path)
|
12
|
+
vcs_file_path = screenshot_path.relative_path_from(Screenshot.root)
|
13
|
+
|
14
|
+
redirect_target = "#{checkout_path} #{SILENCE_ERRORS}"
|
15
|
+
show_command = "git show HEAD~0:./#{vcs_file_path}"
|
16
|
+
if Screenshot.use_lfs
|
17
|
+
`#{show_command} | git lfs smudge > #{redirect_target} ; exit ${PIPESTATUS[0]}`
|
15
18
|
else
|
16
19
|
`#{show_command} > #{redirect_target}`
|
17
20
|
end
|
18
|
-
FileUtils.rm_f(target_file_name) unless $CHILD_STATUS == 0
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
if $CHILD_STATUS != 0
|
23
|
+
FileUtils.rm_f(checkout_path)
|
24
|
+
false
|
25
|
+
else
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
30
|
+
def self.checkout_vcs(screenshot_path, checkout_path)
|
31
|
+
if svn?
|
32
|
+
restore_svn_revision(screenshot_path, checkout_path)
|
27
33
|
else
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
restore_git_revision(screenshot_path, checkout_path)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.restore_svn_revision(screenshot_path, checkout_path)
|
39
|
+
committed_file_name = screenshot_path + "../.svn/text-base/" + "#{screenshot_path.basename}.svn-base"
|
40
|
+
if committed_file_name.exist?
|
41
|
+
FileUtils.cp(committed_file_name, checkout_path)
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
|
45
|
+
svn_info = `svn info #{screenshot_path} #{SILENCE_ERRORS}`
|
46
|
+
if svn_info.present?
|
47
|
+
wc_root = svn_info.slice(/(?<=Working Copy Root Path: ).*$/)
|
48
|
+
checksum = svn_info.slice(/(?<=Checksum: ).*$/)
|
49
|
+
|
50
|
+
if checksum
|
51
|
+
committed_file_name = "#{wc_root}/.svn/pristine/#{checksum[0..1]}/#{checksum}.svn-base"
|
52
|
+
FileUtils.cp(committed_file_name, checkout_path)
|
53
|
+
return true
|
38
54
|
end
|
39
55
|
end
|
56
|
+
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.svn?
|
61
|
+
(Screenshot.screenshot_area_abs / ".svn").exist?
|
40
62
|
end
|
41
63
|
end
|
42
64
|
end
|
@@ -5,10 +5,10 @@ require "capybara/screenshot/diff/version"
|
|
5
5
|
require "capybara/screenshot/diff/drivers/utils"
|
6
6
|
require "capybara/screenshot/diff/image_compare"
|
7
7
|
require "capybara/screenshot/diff/test_methods"
|
8
|
+
require "capybara/screenshot/diff/screenshoter"
|
8
9
|
|
9
10
|
module Capybara
|
10
11
|
module Screenshot
|
11
|
-
extend Os
|
12
12
|
mattr_accessor :add_driver_path
|
13
13
|
mattr_accessor :add_os_path
|
14
14
|
mattr_accessor :blur_active_element
|
@@ -30,10 +30,10 @@ module Capybara
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def screenshot_area
|
33
|
-
parts = [
|
34
|
-
parts << Capybara.current_driver.to_s if
|
35
|
-
parts <<
|
36
|
-
File.join
|
33
|
+
parts = [Screenshot.save_path]
|
34
|
+
parts << Capybara.current_driver.to_s if Screenshot.add_driver_path
|
35
|
+
parts << Os.name if Screenshot.add_os_path
|
36
|
+
File.join(*parts)
|
37
37
|
end
|
38
38
|
|
39
39
|
def screenshot_area_abs
|
@@ -44,8 +44,8 @@ module Capybara
|
|
44
44
|
# Module to track screen shot changes
|
45
45
|
module Diff
|
46
46
|
include Capybara::DSL
|
47
|
-
include Capybara::Screenshot::Os
|
48
47
|
|
48
|
+
mattr_accessor(:delayed) { true }
|
49
49
|
mattr_accessor :area_size_limit
|
50
50
|
mattr_accessor :color_distance_limit
|
51
51
|
mattr_accessor(:enabled) { true }
|
@@ -54,6 +54,8 @@ module Capybara
|
|
54
54
|
mattr_accessor(:driver) { :auto }
|
55
55
|
mattr_accessor :tolerance
|
56
56
|
|
57
|
+
mattr_accessor(:screenshoter) { Screenshoter }
|
58
|
+
|
57
59
|
AVAILABLE_DRIVERS = Utils.detect_available_drivers.freeze
|
58
60
|
ASSERTION = Utils.detect_test_framework_assert
|
59
61
|
|
@@ -65,7 +67,7 @@ module Capybara
|
|
65
67
|
shift_distance_limit: shift_distance_limit,
|
66
68
|
skip_area: skip_area,
|
67
69
|
stability_time_limit: Screenshot.stability_time_limit,
|
68
|
-
tolerance: tolerance || (driver == :vips ? 0.001 : nil),
|
70
|
+
tolerance: tolerance || ((driver == :vips) ? 0.001 : nil),
|
69
71
|
wait: Capybara.default_max_wait_time
|
70
72
|
}
|
71
73
|
end
|
@@ -73,19 +75,13 @@ module Capybara
|
|
73
75
|
def self.included(klass)
|
74
76
|
klass.include TestMethods
|
75
77
|
klass.setup do
|
76
|
-
if
|
77
|
-
if page.driver.respond_to?(:resize)
|
78
|
-
page.driver.resize(*Capybara::Screenshot.window_size)
|
79
|
-
elsif selenium?
|
80
|
-
page.driver.browser.manage.window.resize_to(*Capybara::Screenshot.window_size)
|
81
|
-
end
|
82
|
-
end
|
78
|
+
BrowserHelpers.resize_to(Screenshot.window_size) if Screenshot.window_size
|
83
79
|
end
|
84
80
|
|
85
81
|
klass.teardown do
|
86
|
-
if
|
82
|
+
if Screenshot.active? && @test_screenshots.present?
|
87
83
|
track_failures(@test_screenshots, caller)
|
88
|
-
@test_screenshots
|
84
|
+
@test_screenshots.clear
|
89
85
|
end
|
90
86
|
end
|
91
87
|
end
|
@@ -96,7 +92,7 @@ module Capybara
|
|
96
92
|
|
97
93
|
def track_failures(screenshots, original_caller)
|
98
94
|
test_screenshot_errors = screenshots.map do |caller, name, compare|
|
99
|
-
assert_image_not_changed(
|
95
|
+
assert_image_not_changed(name, compare)
|
100
96
|
end
|
101
97
|
|
102
98
|
test_screenshot_errors.compact!
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Screenshot
|
3
|
+
def self.root=: ((String | Pathname) path) -> Pathname
|
4
|
+
|
5
|
+
def self.root: -> Pathname
|
6
|
+
|
7
|
+
def self.active?: () -> boolish
|
8
|
+
|
9
|
+
def self.screenshot_area: () -> String
|
10
|
+
|
11
|
+
def self.screenshot_area_abs: () -> Pathname
|
12
|
+
|
13
|
+
# Module to track screen shot changes
|
14
|
+
module Diff
|
15
|
+
AVAILABLE_DRIVERS: Array[(:vips | :chunky_png)]
|
16
|
+
|
17
|
+
ASSERTION: (top | RuntimeError)
|
18
|
+
|
19
|
+
def self.default_options: () -> ScreenshotMatcher::input_options
|
20
|
+
|
21
|
+
def self.included: (top klass) -> void
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def track_failures: (Array[untyped] screenshots, (Array[String] | String) original_caller) -> void
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Screenshot
|
3
|
+
module Diff
|
4
|
+
class Difference
|
5
|
+
attr_reader comparison: ImageCompare::Comparison
|
6
|
+
|
7
|
+
def different?: () -> bool
|
8
|
+
|
9
|
+
def base_image: () -> top
|
10
|
+
|
11
|
+
def options: () -> Drivers::BaseDriver::options_entity
|
12
|
+
|
13
|
+
def tolerance: () -> Numeric?
|
14
|
+
|
15
|
+
def area_size_limit: () -> Numeric?
|
16
|
+
|
17
|
+
def blank?: () -> bool
|
18
|
+
|
19
|
+
def region_area_size: () -> Numeric
|
20
|
+
|
21
|
+
def ratio: () -> Numeric?
|
22
|
+
|
23
|
+
def to_h: () -> Hash[Symbol, untyped]
|
24
|
+
|
25
|
+
def coordinates: () -> Region::raw_region_entity
|
26
|
+
|
27
|
+
def inspect: () -> String
|
28
|
+
|
29
|
+
def tolerable?: () -> bool
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Screenshot
|
3
|
+
module Diff
|
4
|
+
module Drivers
|
5
|
+
class BaseDriver[ImageEntity]
|
6
|
+
|
7
|
+
type images_entity[out T] = [T, T]
|
8
|
+
type dimension_entity = [Numeric, Numeric]
|
9
|
+
|
10
|
+
type options_entity = {
|
11
|
+
area_size_limit?: Numeric?,
|
12
|
+
color_distance_limit?: Numeric?,
|
13
|
+
driver: (:auto | :vips | :chunky_png | VipsDriver | ChunkyPNGDriver)?,
|
14
|
+
dimensions: dimension_entity?,
|
15
|
+
median_filter_window_size: Numeric?,
|
16
|
+
shift_distance_limit?: Numeric?,
|
17
|
+
skip_area?: Array[Region]?,
|
18
|
+
stability_time_limit?: Numeric?,
|
19
|
+
tolerance?: Numeric?,
|
20
|
+
wait?: Numeric?
|
21
|
+
}
|
22
|
+
|
23
|
+
type color = [Integer, Integer, Integer, Integer]
|
24
|
+
|
25
|
+
def find_difference_region: (ImageEntity new_image, ImageEntity old_image, Numeric color_distance_limit, Numeric _shift_distance_limit, Integer _area_size_limit, ?fast_fail: bool) -> Difference
|
26
|
+
|
27
|
+
def inscribed?: (dimension_entity dimensions, ImageEntity i) -> boolish
|
28
|
+
|
29
|
+
def crop: (Region region, ImageEntity i) -> ImageEntity
|
30
|
+
|
31
|
+
def filter_image_with_median: (ImageEntity image, Numeric median_filter_window_size) -> ImageEntity
|
32
|
+
|
33
|
+
def add_black_box: (ImageEntity memo, Region region) -> void
|
34
|
+
|
35
|
+
def difference_level: (ImageEntity diff_mask, ImageEntity old_img, Region _region) -> Float
|
36
|
+
|
37
|
+
def image_area_size: (ImageEntity old_img) -> Integer
|
38
|
+
|
39
|
+
def height_for: (ImageEntity image) -> Integer
|
40
|
+
|
41
|
+
def width_for: (ImageEntity image) -> Integer
|
42
|
+
|
43
|
+
# Vips could not work with the same file. Per each process we require to create new file
|
44
|
+
def save_image_to: (ImageEntity image, String filename) -> void
|
45
|
+
|
46
|
+
def resize_image_to: (ImageEntity image, Integer new_width, Integer new_height) -> ImageEntity
|
47
|
+
|
48
|
+
def load_images: (String old_file_name, String new_file_name) -> images_entity[ImageEntity]
|
49
|
+
|
50
|
+
def from_file: (TestMethods::path_entity filename) -> ImageEntity
|
51
|
+
|
52
|
+
def dimension: (ImageEntity image) -> dimension_entity
|
53
|
+
|
54
|
+
def draw_rectangles: (images_entity[ImageEntity] images, Region region, color rgba, Integer offset) -> void
|
55
|
+
|
56
|
+
def same_pixels?: () -> boolish
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.for: (ScreenshotMatcher::input_options) -> (VipsDriver | ChunkyPNGDriver)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Capybara
|
2
|
+
class Result
|
3
|
+
def map: () -> Result
|
4
|
+
end
|
5
|
+
module Screenshot
|
6
|
+
module BrowserHelpers
|
7
|
+
def self.current_capybara_driver_class: () -> top
|
8
|
+
|
9
|
+
def self.selenium?: () -> boolish?
|
10
|
+
|
11
|
+
def self.window_size_is_wrong?: () -> boolish
|
12
|
+
|
13
|
+
def self.bounds_for_css: (*String css_selectors) -> Array[Region::raw_region_entity]
|
14
|
+
|
15
|
+
IMAGE_WAIT_SCRIPT: String
|
16
|
+
|
17
|
+
def self.pending_image_to_load: () -> top?
|
18
|
+
|
19
|
+
HIDE_CARET_SCRIPT: String
|
20
|
+
|
21
|
+
def self.hide_caret: () -> void
|
22
|
+
|
23
|
+
FIND_ACTIVE_ELEMENT_SCRIPT: String
|
24
|
+
|
25
|
+
type capybara_element = top
|
26
|
+
|
27
|
+
def self.blur_from_focused_element: () -> capybara_element?
|
28
|
+
|
29
|
+
GET_BOUNDING_CLIENT_RECT_SCRIPT: String
|
30
|
+
|
31
|
+
def self.all_visible_regions_for: (String selector) -> Array[Region::raw_region_entity]
|
32
|
+
|
33
|
+
def self.region_for: (Result element) -> Region::raw_region_entity
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ChunkyPNG
|
2
|
+
class Canvas
|
3
|
+
end
|
4
|
+
|
5
|
+
class Image
|
6
|
+
def self.from_blob: (String str) -> Image
|
7
|
+
|
8
|
+
def self.from_file: (String filename) -> Image
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Capybara
|
13
|
+
module Screenshot
|
14
|
+
module Diff
|
15
|
+
module Drivers
|
16
|
+
class ChunkyPNGDriver < BaseDriver[ChunkyPNG::Canvas]
|
17
|
+
|
18
|
+
def _load_images: (String old_file, String new_file) -> [ChunkyPNG::Image, ChunkyPNG::Image]
|
19
|
+
|
20
|
+
class DifferenceRegionFinder
|
21
|
+
def find_diff_rectangle: (
|
22
|
+
ChunkyPNG::Image org_img,
|
23
|
+
ChunkyPNG::Image new_img,
|
24
|
+
(Region | Region::raw_region_entity) area_coordinates,
|
25
|
+
cache: ImageCompare::cache_entity
|
26
|
+
) -> Region?
|
27
|
+
|
28
|
+
def find_top: (
|
29
|
+
ChunkyPNG::Image old_img,
|
30
|
+
ChunkyPNG::Image new_img,
|
31
|
+
cache: ImageCompare::cache_entity
|
32
|
+
) -> Region::raw_region_entity?
|
33
|
+
|
34
|
+
def find_left_right_and_top: (
|
35
|
+
ChunkyPNG::Image old_img,
|
36
|
+
ChunkyPNG::Image new_img,
|
37
|
+
(Region | Region::raw_region_entity) region,
|
38
|
+
cache: ImageCompare::cache_entity
|
39
|
+
) -> Region::raw_region_entity
|
40
|
+
|
41
|
+
def find_bottom: (
|
42
|
+
ChunkyPNG::Image old_img,
|
43
|
+
ChunkyPNG::Image new_img,
|
44
|
+
Integer left,
|
45
|
+
Integer right,
|
46
|
+
Integer bottom,
|
47
|
+
cache: ImageCompare::cache_entity
|
48
|
+
) -> Integer
|
49
|
+
|
50
|
+
def same_color?: (
|
51
|
+
ChunkyPNG::Image old_img,
|
52
|
+
ChunkyPNG::Image new_img,
|
53
|
+
Integer x,
|
54
|
+
Integer y,
|
55
|
+
?cache: ImageCompare::cache_entity
|
56
|
+
) -> boolish
|
57
|
+
|
58
|
+
def skipped_region?: (Integer x, Integer y) -> boolish
|
59
|
+
|
60
|
+
def color_distance_at: (
|
61
|
+
ChunkyPNG::Image new_img,
|
62
|
+
ChunkyPNG::Image old_img,
|
63
|
+
Integer x,
|
64
|
+
Integer y,
|
65
|
+
shift_distance_limit: Numeric?
|
66
|
+
) -> Float
|
67
|
+
|
68
|
+
def shift_distance_at: (
|
69
|
+
ChunkyPNG::Image new_img,
|
70
|
+
ChunkyPNG::Image old_img,
|
71
|
+
Integer x,
|
72
|
+
Integer y,
|
73
|
+
color_distance_limit: Numeric?
|
74
|
+
) -> Numeric
|
75
|
+
|
76
|
+
def color_matches: (
|
77
|
+
ChunkyPNG::Image new_img,
|
78
|
+
Integer org_color,
|
79
|
+
Integer x,
|
80
|
+
Integer y,
|
81
|
+
Numeric? color_distance_limit
|
82
|
+
) -> boolish
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Capybara
|
2
|
+
module Screenshot
|
3
|
+
module Diff
|
4
|
+
module Utils
|
5
|
+
def self.detect_available_drivers: () -> Array[(:vips | :chunky_png)]
|
6
|
+
|
7
|
+
def self.find_driver_class_for: [T] (Symbol driver) -> T
|
8
|
+
|
9
|
+
def self.detect_test_framework_assert: [T < Exception] () -> T
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ::Vips
|
2
|
+
class Image
|
3
|
+
def self.new_from_file: (String filename) -> Image
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module Capybara
|
8
|
+
module Screenshot
|
9
|
+
module Diff
|
10
|
+
module Drivers
|
11
|
+
class VipsDriver < BaseDriver[Vips::Image]
|
12
|
+
class VipsUtil
|
13
|
+
def self.difference_area: (Vips::Image old_image, Vips::Image new_image, ?color_distance: ::Integer) -> Numeric
|
14
|
+
|
15
|
+
def self.difference_area_size_by: (Vips::Image difference_mask) -> Numeric
|
16
|
+
|
17
|
+
def self.difference_mask: (Vips::Image, Vips::Image, ?Numeric? color_distance) -> Vips::Image
|
18
|
+
|
19
|
+
def self.difference_region_by: (Vips::Image diff_mask) -> Region?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|