capybara-screenshot-diff 1.6.2 → 1.8.3
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 +6 -3
- data/gems.rb +8 -2
- data/lib/capybara/screenshot/diff/browser_helpers.rb +102 -0
- 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 +193 -252
- data/lib/capybara/screenshot/diff/drivers/utils.rb +25 -0
- data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +65 -100
- data/lib/capybara/screenshot/diff/drivers.rb +16 -0
- data/lib/capybara/screenshot/diff/image_compare.rb +138 -154
- data/lib/capybara/screenshot/diff/os.rb +1 -1
- data/lib/capybara/screenshot/diff/region.rb +86 -0
- data/lib/capybara/screenshot/diff/screenshot_matcher.rb +128 -0
- data/lib/capybara/screenshot/diff/screenshoter.rb +136 -0
- data/lib/capybara/screenshot/diff/stabilization.rb +0 -210
- data/lib/capybara/screenshot/diff/stable_screenshoter.rb +106 -0
- data/lib/capybara/screenshot/diff/test_methods.rb +57 -63
- data/lib/capybara/screenshot/diff/vcs.rb +48 -21
- data/lib/capybara/screenshot/diff/version.rb +1 -1
- data/lib/capybara/screenshot/diff.rb +38 -35
- 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 +30 -25
- data/.gitattributes +0 -4
- data/.github/workflows/lint.yml +0 -25
- data/.github/workflows/test.yml +0 -120
- data/.gitignore +0 -12
- data/.standard.yml +0 -12
- data/CONTRIBUTING.md +0 -22
- data/Dockerfile +0 -60
- data/README.md +0 -555
- 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/rails52.gemfile +0 -6
- 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,48 +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"
|
13
|
+
require_relative "browser_helpers"
|
14
|
+
require_relative "region"
|
15
|
+
|
16
|
+
require_relative "screenshot_matcher"
|
11
17
|
|
12
18
|
# Add the `screenshot` method to ActionDispatch::IntegrationTest
|
13
19
|
module Capybara
|
14
20
|
module Screenshot
|
15
21
|
module Diff
|
16
22
|
module TestMethods
|
17
|
-
include Stabilization
|
18
|
-
include Vcs
|
19
|
-
|
20
23
|
def initialize(*)
|
21
24
|
super
|
22
25
|
@screenshot_counter = nil
|
23
26
|
@screenshot_group = nil
|
24
27
|
@screenshot_section = nil
|
25
28
|
@test_screenshot_errors = nil
|
26
|
-
@test_screenshots =
|
29
|
+
@test_screenshots = []
|
27
30
|
end
|
28
31
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
32
|
+
def build_full_name(name)
|
33
|
+
if @screenshot_counter
|
34
|
+
name = format("%02i_#{name}", @screenshot_counter)
|
35
|
+
@screenshot_counter += 1
|
36
|
+
end
|
35
37
|
|
36
|
-
|
37
|
-
File.join group_parts.<<(name).map(&:to_s)
|
38
|
+
File.join(*group_parts.push(name.to_s))
|
38
39
|
end
|
39
40
|
|
40
41
|
def screenshot_dir
|
41
|
-
File.join
|
42
|
-
end
|
43
|
-
|
44
|
-
def current_capybara_driver_class
|
45
|
-
Capybara.current_session.driver.class
|
46
|
-
end
|
47
|
-
|
48
|
-
def selenium?
|
49
|
-
current_capybara_driver_class <= Capybara::Selenium::Driver
|
42
|
+
File.join(*([Screenshot.screenshot_area] + group_parts))
|
50
43
|
end
|
51
44
|
|
52
45
|
def screenshot_section(name)
|
@@ -55,66 +48,67 @@ module Capybara
|
|
55
48
|
|
56
49
|
def screenshot_group(name)
|
57
50
|
@screenshot_group = name.to_s
|
58
|
-
@screenshot_counter = 0
|
51
|
+
@screenshot_counter = @screenshot_group.present? ? 0 : nil
|
59
52
|
return unless Screenshot.active? && name.present?
|
60
53
|
|
61
54
|
FileUtils.rm_rf screenshot_dir
|
62
55
|
end
|
63
56
|
|
64
|
-
|
65
|
-
|
57
|
+
def schedule_match_job(job)
|
58
|
+
(@test_screenshots ||= []) << job
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def group_parts
|
63
|
+
parts = []
|
64
|
+
parts << @screenshot_section if @screenshot_section.present?
|
65
|
+
parts << @screenshot_group if @screenshot_group.present?
|
66
|
+
parts
|
67
|
+
end
|
68
|
+
|
69
|
+
def screenshot(name, skip_stack_frames: 0, **options)
|
66
70
|
return false unless Screenshot.active?
|
67
|
-
return false if window_size_is_wrong?
|
68
71
|
|
69
|
-
|
72
|
+
screenshot_full_name = build_full_name(name)
|
73
|
+
job = build_screenshot_matches_job(screenshot_full_name, options)
|
70
74
|
|
71
|
-
|
72
|
-
wait = driver_options[:wait]
|
73
|
-
crop = driver_options.delete(:crop)
|
75
|
+
return false unless job
|
74
76
|
|
75
|
-
|
76
|
-
if driver_options[:skip_area]
|
77
|
-
driver_options[:skip_area] = driver_options[:skip_area].compact.flatten&.each_slice(4)&.to_a
|
78
|
-
end
|
77
|
+
job.prepend(caller[skip_stack_frames])
|
79
78
|
|
80
|
-
if
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
comparison = ImageCompare.new(file_name, nil, driver_options)
|
89
|
-
checkout_vcs(name, comparison)
|
90
|
-
begin
|
91
|
-
blurred_input = prepare_page_for_screenshot(timeout: wait)
|
92
|
-
if stability_time_limit
|
93
|
-
take_stable_screenshot(comparison, stability_time_limit: stability_time_limit, wait: wait, crop: crop)
|
94
|
-
else
|
95
|
-
take_right_size_screenshot(comparison, crop: crop)
|
79
|
+
if Screenshot::Diff.delayed
|
80
|
+
schedule_match_job(job)
|
81
|
+
else
|
82
|
+
error_msg = assert_image_not_changed(*job)
|
83
|
+
if error_msg
|
84
|
+
error = ASSERTION.new(error_msg)
|
85
|
+
error.set_backtrace(caller(2))
|
86
|
+
raise error
|
96
87
|
end
|
97
|
-
ensure
|
98
|
-
blurred_input&.click
|
99
88
|
end
|
89
|
+
end
|
100
90
|
|
101
|
-
|
91
|
+
def assert_image_not_changed(caller, name, comparison)
|
92
|
+
result = comparison.different?
|
102
93
|
|
103
|
-
|
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
|
104
100
|
|
105
|
-
|
106
|
-
end
|
101
|
+
return unless result
|
107
102
|
|
108
|
-
|
109
|
-
selenium? && Screenshot.window_size &&
|
110
|
-
page.driver.browser.manage.window.size !=
|
111
|
-
::Selenium::WebDriver::Dimension.new(*Screenshot.window_size)
|
103
|
+
"Screenshot does not match for '#{name}' #{comparison.error_message}\n#{caller}"
|
112
104
|
end
|
113
105
|
|
114
|
-
|
115
|
-
return unless comparison.different?
|
106
|
+
private
|
116
107
|
|
117
|
-
|
108
|
+
def build_screenshot_matches_job(screenshot_full_name, options)
|
109
|
+
ScreenshotMatcher
|
110
|
+
.new(screenshot_full_name, options)
|
111
|
+
.build_screenshot_matches_job
|
118
112
|
end
|
119
113
|
end
|
120
114
|
end
|
@@ -1,41 +1,68 @@
|
|
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} > #{checkout_path}.tmp #{SILENCE_ERRORS}`
|
18
|
+
if $CHILD_STATUS == 0
|
19
|
+
`git lfs smudge < #{checkout_path}.tmp > #{redirect_target}`
|
20
|
+
end
|
21
|
+
File.delete "#{checkout_path}.tmp"
|
15
22
|
else
|
16
23
|
`#{show_command} > #{redirect_target}`
|
17
24
|
end
|
18
|
-
|
25
|
+
|
26
|
+
if $CHILD_STATUS != 0
|
27
|
+
FileUtils.rm_f(checkout_path)
|
28
|
+
false
|
29
|
+
else
|
30
|
+
true
|
31
|
+
end
|
19
32
|
end
|
20
33
|
|
21
|
-
def checkout_vcs(
|
22
|
-
|
23
|
-
|
24
|
-
committed_file_name = svn_file_name
|
25
|
-
FileUtils.cp committed_file_name, comparison.old_file_name
|
34
|
+
def self.checkout_vcs(screenshot_path, checkout_path)
|
35
|
+
if svn?
|
36
|
+
restore_svn_revision(screenshot_path, checkout_path)
|
26
37
|
else
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
38
|
+
restore_git_revision(screenshot_path, checkout_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.restore_svn_revision(screenshot_path, checkout_path)
|
43
|
+
committed_file_name = screenshot_path + "../.svn/text-base/" + "#{screenshot_path.basename}.svn-base"
|
44
|
+
if committed_file_name.exist?
|
45
|
+
FileUtils.cp(committed_file_name, checkout_path)
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
|
49
|
+
svn_info = `svn info #{screenshot_path} #{SILENCE_ERRORS}`
|
50
|
+
if svn_info.present?
|
51
|
+
wc_root = svn_info.slice(/(?<=Working Copy Root Path: ).*$/)
|
52
|
+
checksum = svn_info.slice(/(?<=Checksum: ).*$/)
|
53
|
+
|
54
|
+
if checksum
|
55
|
+
committed_file_name = "#{wc_root}/.svn/pristine/#{checksum[0..1]}/#{checksum}.svn-base"
|
56
|
+
FileUtils.cp(committed_file_name, checkout_path)
|
57
|
+
return true
|
37
58
|
end
|
38
59
|
end
|
60
|
+
|
61
|
+
false
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.svn?
|
65
|
+
(Screenshot.screenshot_area_abs / ".svn").exist?
|
39
66
|
end
|
40
67
|
end
|
41
68
|
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,23 +44,20 @@ 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 }
|
52
52
|
mattr_accessor :shift_distance_limit
|
53
53
|
mattr_accessor :skip_area
|
54
54
|
mattr_accessor(:driver) { :auto }
|
55
|
-
mattr_accessor
|
55
|
+
mattr_accessor :tolerance
|
56
|
+
|
57
|
+
mattr_accessor(:screenshoter) { Screenshoter }
|
56
58
|
|
57
59
|
AVAILABLE_DRIVERS = Utils.detect_available_drivers.freeze
|
58
|
-
|
59
|
-
require "minitest"
|
60
|
-
ASSERTION = Minitest::Assertion
|
61
|
-
rescue
|
62
|
-
ASSERTION = RuntimeError
|
63
|
-
end
|
60
|
+
ASSERTION = Utils.detect_test_framework_assert
|
64
61
|
|
65
62
|
def self.default_options
|
66
63
|
{
|
@@ -70,7 +67,7 @@ module Capybara
|
|
70
67
|
shift_distance_limit: shift_distance_limit,
|
71
68
|
skip_area: skip_area,
|
72
69
|
stability_time_limit: Screenshot.stability_time_limit,
|
73
|
-
tolerance: tolerance,
|
70
|
+
tolerance: tolerance || ((driver == :vips) ? 0.001 : nil),
|
74
71
|
wait: Capybara.default_max_wait_time
|
75
72
|
}
|
76
73
|
end
|
@@ -78,30 +75,36 @@ module Capybara
|
|
78
75
|
def self.included(klass)
|
79
76
|
klass.include TestMethods
|
80
77
|
klass.setup do
|
81
|
-
if
|
82
|
-
if page.driver.respond_to?(:resize)
|
83
|
-
page.driver.resize(*Capybara::Screenshot.window_size)
|
84
|
-
elsif selenium?
|
85
|
-
page.driver.browser.manage.window.resize_to(*Capybara::Screenshot.window_size)
|
86
|
-
end
|
87
|
-
end
|
78
|
+
BrowserHelpers.resize_to(Screenshot.window_size) if Screenshot.window_size
|
88
79
|
end
|
89
80
|
|
90
81
|
klass.teardown do
|
91
|
-
if
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
82
|
+
if Screenshot.active? && @test_screenshots.present?
|
83
|
+
track_failures(@test_screenshots)
|
84
|
+
@test_screenshots.clear
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
EMPTY_LINE = "\n\n"
|
92
|
+
|
93
|
+
def track_failures(screenshots)
|
94
|
+
test_screenshot_errors = screenshots.map do |caller, name, compare|
|
95
|
+
assert_image_not_changed(caller, name, compare)
|
96
|
+
end
|
97
|
+
|
98
|
+
test_screenshot_errors.compact!
|
99
|
+
|
100
|
+
unless test_screenshot_errors.empty?
|
101
|
+
error = ASSERTION.new(test_screenshot_errors.join(EMPTY_LINE))
|
102
|
+
error.set_backtrace([])
|
103
|
+
|
104
|
+
if is_a?(::Minitest::Runnable)
|
105
|
+
failures << error
|
106
|
+
else
|
107
|
+
raise error
|
105
108
|
end
|
106
109
|
end
|
107
110
|
end
|
@@ -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) -> 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
|