capybara-screenshot-diff 1.7.1 → 1.8.1
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 +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
|