capybara-screenshot-diff 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +29 -0
  3. data/capybara-screenshot-diff.gemspec +7 -4
  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 +16 -0
  11. data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +53 -103
  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 +137 -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 +36 -27
  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: e982564438ee16c8ae6900407e80ab1921888bd83b14fc6efc1c9a20fb6b79d5
4
+ data.tar.gz: 4893ded8cd25dbf93d9147b21e3a1bf09d80c544a390648eae58ef46dca85c78
5
5
  SHA512:
6
- metadata.gz: 4a0830ab529fcbacf843e3ea7ae168a752ca4b5b03f613e81437e5e7856037856ac9b7562e6a78304ecb8257ac9286456db669fe8e1763b94db1436e79c59439
7
- data.tar.gz: 00d73d7a68b91b8ec35ae828b27141723c6cc67ed57d73b7780e3b8942d11eb383f410225af347e0acf078459eb674e7da93fa329758b5cc4a475a4129fccdf1
6
+ metadata.gz: 146c1928e4fd32ac25d7ad6813f81adb6e6a82004ab2bd589281e8fbc130001f4cddea57e706d7023dcb760a0d907d9a766375ef25a851e44962db6bbdd3e80a
7
+ data.tar.gz: 474fca1d1a8e27508593efe4517f6fe2d58608693acba531943e3220d6ae169445963517da6b40b5f7c095f6ef27f038cf57c397f7e17e0f3cae728307f085cd
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
- spec.add_runtime_dependency "chunky_png", "~> 1.3"
28
+ spec.add_runtime_dependency "chunky_png", ">= 1.3", "< 2"
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