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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +29 -0
  3. data/capybara-screenshot-diff.gemspec +6 -3
  4. data/gems.rb +8 -2
  5. data/lib/capybara/screenshot/diff/browser_helpers.rb +29 -28
  6. data/lib/capybara/screenshot/diff/cucumber.rb +11 -0
  7. data/lib/capybara/screenshot/diff/difference.rb +63 -0
  8. data/lib/capybara/screenshot/diff/drivers/base_driver.rb +42 -0
  9. data/lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb +188 -260
  10. data/lib/capybara/screenshot/diff/drivers/utils.rb +18 -0
  11. data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +54 -104
  12. data/lib/capybara/screenshot/diff/drivers.rb +16 -0
  13. data/lib/capybara/screenshot/diff/image_compare.rb +125 -154
  14. data/lib/capybara/screenshot/diff/os.rb +1 -1
  15. data/lib/capybara/screenshot/diff/screenshot_matcher.rb +128 -0
  16. data/lib/capybara/screenshot/diff/screenshoter.rb +136 -0
  17. data/lib/capybara/screenshot/diff/stabilization.rb +0 -184
  18. data/lib/capybara/screenshot/diff/stable_screenshoter.rb +106 -0
  19. data/lib/capybara/screenshot/diff/test_methods.rb +51 -90
  20. data/lib/capybara/screenshot/diff/vcs.rb +44 -22
  21. data/lib/capybara/screenshot/diff/version.rb +1 -1
  22. data/lib/capybara/screenshot/diff.rb +13 -17
  23. data/sig/capybara/screenshot/diff/diff.rbs +28 -0
  24. data/sig/capybara/screenshot/diff/difference.rbs +33 -0
  25. data/sig/capybara/screenshot/diff/drivers/base_driver.rbs +63 -0
  26. data/sig/capybara/screenshot/diff/drivers/browser_helpers.rbs +36 -0
  27. data/sig/capybara/screenshot/diff/drivers/chunky_png_driver.rbs +89 -0
  28. data/sig/capybara/screenshot/diff/drivers/utils.rbs +13 -0
  29. data/sig/capybara/screenshot/diff/drivers/vips_driver.rbs +25 -0
  30. data/sig/capybara/screenshot/diff/image_compare.rbs +93 -0
  31. data/sig/capybara/screenshot/diff/os.rbs +11 -0
  32. data/sig/capybara/screenshot/diff/region.rbs +43 -0
  33. data/sig/capybara/screenshot/diff/screenshot_matcher.rbs +60 -0
  34. data/sig/capybara/screenshot/diff/screenshoter.rbs +48 -0
  35. data/sig/capybara/screenshot/diff/stable_screenshoter.rbs +29 -0
  36. data/sig/capybara/screenshot/diff/test_methods.rbs +39 -0
  37. data/sig/capybara/screenshot/diff/vcs.rbs +17 -0
  38. metadata +28 -25
  39. data/.gitattributes +0 -4
  40. data/.github/dependabot.yml +0 -8
  41. data/.github/workflows/lint.yml +0 -25
  42. data/.github/workflows/test.yml +0 -138
  43. data/.gitignore +0 -14
  44. data/.standard.yml +0 -12
  45. data/CONTRIBUTING.md +0 -24
  46. data/Dockerfile +0 -59
  47. data/README.md +0 -567
  48. data/bin/bundle +0 -114
  49. data/bin/console +0 -15
  50. data/bin/install-vips +0 -11
  51. data/bin/rake +0 -27
  52. data/bin/setup +0 -8
  53. data/bin/standardrb +0 -29
  54. data/gemfiles/rails60_gems.rb +0 -8
  55. data/gemfiles/rails61_gems.rb +0 -7
  56. data/gemfiles/rails70_gems.rb +0 -7
  57. data/tmp/.keep +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5720ce552818a78eecc14cea2ba443d1788c282d21a063c0088109f3115e78b
4
- data.tar.gz: fe2635d43016fa6350687c77f7d17ff1a11beb1d0e56f7357b63a04e4fb590ec
3
+ metadata.gz: 87baa5dd7c412b251fbd55171a131700bada4ec3b3a09739b70482178fce85f6
4
+ data.tar.gz: 18283f48c01a863c6af2d4a6ef6dce9f987868ad5d27978b3f1aa4f2feb81073
5
5
  SHA512:
6
- metadata.gz: 4a0830ab529fcbacf843e3ea7ae168a752ca4b5b03f613e81437e5e7856037856ac9b7562e6a78304ecb8257ac9286456db669fe8e1763b94db1436e79c59439
7
- data.tar.gz: 00d73d7a68b91b8ec35ae828b27141723c6cc67ed57d73b7780e3b8942d11eb383f410225af347e0acf078459eb674e7da93fa329758b5cc4a475a4129fccdf1
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 = defined?(JRUBY_VERSION) ? ">= 2.6.0" : ">= 2.7.0"
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 { |f| f.match(%r{^(test|spec|features)/}) }
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.0", "< 8"
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 current_capybara_driver_class
9
- Capybara.current_session.driver.class
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
- Screenshot.window_size &&
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
- page.evaluate_script(FIND_ACTIVE_ELEMENT_SCRIPT)
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
- private
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 create_output_directory_for(file_name)
97
- FileUtils.mkdir_p File.dirname(file_name)
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