capybara-screenshot-diff 1.7.1 → 1.8.1
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/Rakefile +29 -0
- data/capybara-screenshot-diff.gemspec +6 -3
- 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 +18 -0
- data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +54 -104
- 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 +136 -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 +28 -25
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87baa5dd7c412b251fbd55171a131700bada4ec3b3a09739b70482178fce85f6
|
4
|
+
data.tar.gz: 18283f48c01a863c6af2d4a6ef6dce9f987868ad5d27978b3f1aa4f2feb81073
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6295286f5267b8b956cb8d2f85599812567dae1b228ab9c15720d45fcf37a33a780cfaccbe9b2ab7ec350a99b3e2426594af4eb3b7e3aa4f158d0cba83bb7e26
|
7
|
+
data.tar.gz: c7f891a279ffd74da9ebc3bd1c1f57966010914ff258d84ca62940e03b5efc11ed6b14f72beefc140127f11799c07be9b49a32d6b0bce63f9329cd5255730012
|
data/Rakefile
CHANGED
@@ -16,3 +16,32 @@ Rake::TestTask.new("test:integration") do |t|
|
|
16
16
|
t.libs << "lib"
|
17
17
|
t.test_files = FileList["test/integration/**/*_test.rb"]
|
18
18
|
end
|
19
|
+
|
20
|
+
Rake::TestTask.new("test:signatures") do |t|
|
21
|
+
ENV["RBS_TEST_DOUBLE_SUITE"] ||= "minitest"
|
22
|
+
ENV["RBS_TEST_TARGET"] ||= "Capybara::Screenshot::Diff::*"
|
23
|
+
ENV["RBS_TEST_OPT"] ||= "-rset -rpathname -Isig"
|
24
|
+
|
25
|
+
t.libs << "test"
|
26
|
+
t.ruby_opts << "-r rbs/test/setup"
|
27
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
28
|
+
end
|
29
|
+
|
30
|
+
task "clobber" do
|
31
|
+
puts "Cleanup tmp/*.png"
|
32
|
+
FileUtils.rm_rf(Dir["./tmp/*"])
|
33
|
+
end
|
34
|
+
|
35
|
+
task "test:benchmark" do
|
36
|
+
require_relative "./scripts/benchmark/find_region_benchmark"
|
37
|
+
benchmark = Capybara::Screenshot::Diff::Drivers::FindRegionBenchmark.new
|
38
|
+
|
39
|
+
puts "For Medium Screen Size: 800x600"
|
40
|
+
benchmark.for_medium_size_screens
|
41
|
+
|
42
|
+
puts ""
|
43
|
+
puts "*" * 100
|
44
|
+
|
45
|
+
puts "For Small Screen Size: 80x60"
|
46
|
+
benchmark.for_small_images
|
47
|
+
end
|
@@ -12,15 +12,18 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.summary = "Track your GUI changes with diff assertions"
|
13
13
|
spec.description = "Save screen shots and track changes with graphical diff"
|
14
14
|
spec.homepage = "https://github.com/donv/capybara-screenshot-diff"
|
15
|
-
spec.required_ruby_version =
|
15
|
+
spec.required_ruby_version = ">= 3.0.0"
|
16
16
|
spec.license = "MIT"
|
17
17
|
spec.metadata["allowed_push_host"] = "https://rubygems.org/"
|
18
|
-
spec.files = `git ls-files -z`.split("\x0").reject
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{(^(\.|tmp|bin|test|spec|features|gemfiles|scripts)/)|(^(\.|Dockerfile|CONTRIBUTING|README))})
|
20
|
+
end
|
21
|
+
|
19
22
|
spec.bindir = "exe"
|
20
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
24
|
spec.require_paths = ["lib"]
|
22
25
|
|
23
|
-
spec.add_runtime_dependency "actionpack", ">= 6.
|
26
|
+
spec.add_runtime_dependency "actionpack", ">= 6.1", "< 8"
|
24
27
|
spec.add_runtime_dependency "capybara", ">= 2", "< 4"
|
25
28
|
spec.add_runtime_dependency "chunky_png", "~> 1.3"
|
26
29
|
end
|
data/gems.rb
CHANGED
@@ -8,7 +8,7 @@ gemspec path: __dir__
|
|
8
8
|
gem "rake"
|
9
9
|
|
10
10
|
# Image processing libraries
|
11
|
-
gem "oily_png", platform: :ruby
|
11
|
+
gem "oily_png", platform: :ruby, git: "https://github.com/donv/oily_png", branch: "patch-2"
|
12
12
|
gem "ruby-vips", require: false
|
13
13
|
|
14
14
|
# Test
|
@@ -18,12 +18,18 @@ gem "simplecov", require: false
|
|
18
18
|
|
19
19
|
# Capybara Server
|
20
20
|
gem "puma", require: false
|
21
|
+
gem "rackup", require: false
|
21
22
|
|
22
23
|
# Capybara Drivers
|
23
24
|
gem "cuprite", require: false
|
24
25
|
gem "selenium-webdriver", require: false
|
25
|
-
gem "webdrivers", require: false
|
26
|
+
gem "webdrivers", "~> 5.0", require: false
|
27
|
+
|
28
|
+
# Test Frameworks
|
29
|
+
# gem "cucumber", require: false
|
30
|
+
# gem "cucumber-rails", require: false
|
26
31
|
|
27
32
|
group :tools do
|
28
33
|
gem "standard", require: false
|
34
|
+
gem "rbs", require: false, platform: :ruby
|
29
35
|
end
|
@@ -5,25 +5,24 @@ require_relative "region"
|
|
5
5
|
module Capybara
|
6
6
|
module Screenshot
|
7
7
|
module BrowserHelpers
|
8
|
-
def
|
9
|
-
|
8
|
+
def self.resize_to(window_size)
|
9
|
+
if session.driver.respond_to?(:resize)
|
10
|
+
session.driver.resize(*window_size)
|
11
|
+
elsif BrowserHelpers.selenium?
|
12
|
+
session.driver.browser.manage.window.resize_to(*window_size)
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
12
|
-
def selenium?
|
16
|
+
def self.selenium?
|
13
17
|
current_capybara_driver_class <= Capybara::Selenium::Driver
|
14
18
|
end
|
15
19
|
|
16
|
-
def window_size_is_wrong?
|
17
|
-
selenium? &&
|
18
|
-
|
19
|
-
page.driver.browser.manage.window.size != ::Selenium::WebDriver::Dimension.new(*Screenshot.window_size)
|
20
|
-
end
|
21
|
-
|
22
|
-
def rect_for(css_selector)
|
23
|
-
all_visible_regions_for(css_selector).first
|
20
|
+
def self.window_size_is_wrong?(expected_window_size = nil)
|
21
|
+
selenium? && expected_window_size &&
|
22
|
+
session.driver.browser.manage.window.size != ::Selenium::WebDriver::Dimension.new(*expected_window_size)
|
24
23
|
end
|
25
24
|
|
26
|
-
def bounds_for_css(*css_selectors)
|
25
|
+
def self.bounds_for_css(*css_selectors)
|
27
26
|
css_selectors.reduce([]) do |regions, selector|
|
28
27
|
regions.concat(all_visible_regions_for(selector))
|
29
28
|
end
|
@@ -38,13 +37,9 @@ module Capybara
|
|
38
37
|
}
|
39
38
|
}
|
40
39
|
return false;
|
41
|
-
}()
|
40
|
+
}(window)
|
42
41
|
JS
|
43
42
|
|
44
|
-
def pending_image_to_load
|
45
|
-
evaluate_script IMAGE_WAIT_SCRIPT
|
46
|
-
end
|
47
|
-
|
48
43
|
HIDE_CARET_SCRIPT = <<~JS
|
49
44
|
if (!document.getElementById('csdHideCaretStyle')) {
|
50
45
|
let style = document.createElement('style');
|
@@ -55,8 +50,8 @@ module Capybara
|
|
55
50
|
}
|
56
51
|
JS
|
57
52
|
|
58
|
-
def hide_caret
|
59
|
-
execute_script(HIDE_CARET_SCRIPT)
|
53
|
+
def self.hide_caret
|
54
|
+
session.execute_script(HIDE_CARET_SCRIPT)
|
60
55
|
end
|
61
56
|
|
62
57
|
FIND_ACTIVE_ELEMENT_SCRIPT = <<~JS
|
@@ -67,11 +62,11 @@ module Capybara
|
|
67
62
|
return ae;
|
68
63
|
}
|
69
64
|
return null;
|
70
|
-
}();
|
65
|
+
}(window);
|
71
66
|
JS
|
72
67
|
|
73
|
-
def blur_from_focused_element
|
74
|
-
|
68
|
+
def self.blur_from_focused_element
|
69
|
+
session.evaluate_script(FIND_ACTIVE_ELEMENT_SCRIPT)
|
75
70
|
end
|
76
71
|
|
77
72
|
GET_BOUNDING_CLIENT_RECT_SCRIPT = <<~JS
|
@@ -83,18 +78,24 @@ module Capybara
|
|
83
78
|
]
|
84
79
|
JS
|
85
80
|
|
86
|
-
def all_visible_regions_for(selector)
|
87
|
-
all(selector, visible: true).map(&method(:region_for))
|
81
|
+
def self.all_visible_regions_for(selector)
|
82
|
+
BrowserHelpers.session.all(selector, visible: true).map(&method(:region_for))
|
88
83
|
end
|
89
84
|
|
90
|
-
def region_for(element)
|
85
|
+
def self.region_for(element)
|
91
86
|
element.evaluate_script(GET_BOUNDING_CLIENT_RECT_SCRIPT).map { |point| point.negative? ? 0 : point.to_i }
|
92
87
|
end
|
93
88
|
|
94
|
-
|
89
|
+
def self.session
|
90
|
+
Capybara.current_session
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.pending_image_to_load
|
94
|
+
BrowserHelpers.session.evaluate_script(IMAGE_WAIT_SCRIPT)
|
95
|
+
end
|
95
96
|
|
96
|
-
def
|
97
|
-
|
97
|
+
def self.current_capybara_driver_class
|
98
|
+
session.driver.class
|
98
99
|
end
|
99
100
|
end
|
100
101
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "capybara/screenshot/diff"
|
4
|
+
require "capybara/screenshot/diff/test_methods"
|
5
|
+
|
6
|
+
World(Capybara::Screenshot::Diff::TestMethods)
|
7
|
+
|
8
|
+
Before do
|
9
|
+
Capybara::Screenshot::Diff.delayed = false
|
10
|
+
Capybara::Screenshot::BrowserHelpers.resize_to(Capybara::Screenshot.window_size) if Capybara::Screenshot.window_size
|
11
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Capybara
|
6
|
+
module Screenshot
|
7
|
+
module Diff
|
8
|
+
class Difference < Struct.new(:region, :meta, :comparison)
|
9
|
+
def different?
|
10
|
+
!(blank? || tolerable?)
|
11
|
+
end
|
12
|
+
|
13
|
+
def base_image
|
14
|
+
comparison.base_image
|
15
|
+
end
|
16
|
+
|
17
|
+
def options
|
18
|
+
comparison.options
|
19
|
+
end
|
20
|
+
|
21
|
+
def tolerance
|
22
|
+
options[:tolerance]
|
23
|
+
end
|
24
|
+
|
25
|
+
def skip_area
|
26
|
+
options[:skip_area]
|
27
|
+
end
|
28
|
+
|
29
|
+
def area_size_limit
|
30
|
+
options[:area_size_limit]
|
31
|
+
end
|
32
|
+
|
33
|
+
def blank?
|
34
|
+
region.nil? || region_area_size.zero?
|
35
|
+
end
|
36
|
+
|
37
|
+
def region_area_size
|
38
|
+
region&.size || 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def ratio
|
42
|
+
meta[:difference_level]
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_h
|
46
|
+
{area_size: region_area_size, region: coordinates}.merge!(meta)
|
47
|
+
end
|
48
|
+
|
49
|
+
def coordinates
|
50
|
+
region&.to_edge_coordinates
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
to_h.to_json
|
55
|
+
end
|
56
|
+
|
57
|
+
def tolerable?
|
58
|
+
!!((area_size_limit && area_size_limit >= region_area_size) || (tolerance && tolerance >= ratio))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "chunky_png"
|
4
|
+
require "capybara/screenshot/diff/difference"
|
5
|
+
|
6
|
+
module Capybara
|
7
|
+
module Screenshot
|
8
|
+
module Diff
|
9
|
+
# Compare two images and determine if they are equal, different, or within some comparison
|
10
|
+
# range considering color values and difference area size.
|
11
|
+
module Drivers
|
12
|
+
class BaseDriver
|
13
|
+
PNG_EXTENSION = ".png"
|
14
|
+
|
15
|
+
def same_dimension?(comparison)
|
16
|
+
dimension(comparison.base_image) == dimension(comparison.new_image)
|
17
|
+
end
|
18
|
+
|
19
|
+
def height_for(image)
|
20
|
+
image.height
|
21
|
+
end
|
22
|
+
|
23
|
+
def width_for(image)
|
24
|
+
image.width
|
25
|
+
end
|
26
|
+
|
27
|
+
def image_area_size(image)
|
28
|
+
width_for(image) * height_for(image)
|
29
|
+
end
|
30
|
+
|
31
|
+
def dimension(image)
|
32
|
+
[width_for(image), height_for(image)]
|
33
|
+
end
|
34
|
+
|
35
|
+
def inscribed?(dimensions, i)
|
36
|
+
width_for(i) < dimensions[0] || height_for(i) < dimensions[1]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|