capybara-screenshot-diff 1.10.2 → 1.10.3
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/lib/capybara/screenshot/diff/browser_helpers.rb +6 -0
- data/lib/capybara/screenshot/diff/region.rb +1 -1
- data/lib/capybara/screenshot/diff/stable_screenshoter.rb +1 -1
- data/lib/capybara/screenshot/diff/test_methods.rb +26 -53
- data/lib/capybara/screenshot/diff/vcs.rb +1 -1
- data/lib/capybara/screenshot/diff/version.rb +1 -1
- data/lib/capybara_screenshot_diff/cucumber.rb +1 -3
- data/lib/capybara_screenshot_diff/dsl.rb +7 -0
- data/lib/capybara_screenshot_diff/minitest.rb +19 -19
- data/lib/capybara_screenshot_diff/rspec.rb +14 -10
- data/lib/capybara_screenshot_diff/screenshot_assertion.rb +127 -0
- data/lib/capybara_screenshot_diff.rb +6 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24a35d04ca598ca2d4acd2ebff19dc3d839a6440de5b4744ec6f7a376d113df0
|
4
|
+
data.tar.gz: 5f1072b91792ce8266e74b9a916bd1f86ae5de04204e666f5d59111605480b3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf944436f2e42f0e9c45bae1ec25e61822d92dac0ccfba259d91dc5bea18233f8397dcd6fa93ac4ef1d8157d0302f512ffa5930031f05656c8a2d2b3fd385a42
|
7
|
+
data.tar.gz: ee75582ecad3092d278ec3d4565b4501483cf71dff433a11f1af912c6848523f6a38223e983de1c7b4b629d88a4e14409051b5ea59490b5719cb9e4487ca8175
|
@@ -5,6 +5,12 @@ require_relative "region"
|
|
5
5
|
module Capybara
|
6
6
|
module Screenshot
|
7
7
|
module BrowserHelpers
|
8
|
+
def self.resize_window_if_needed
|
9
|
+
if ::Capybara::Screenshot.respond_to?(:window_size) && ::Capybara::Screenshot.window_size
|
10
|
+
resize_to(::Capybara::Screenshot.window_size)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
8
14
|
def self.resize_to(window_size)
|
9
15
|
if session.driver.respond_to?(:resize)
|
10
16
|
session.driver.resize(*window_size)
|
@@ -100,7 +100,7 @@ module Capybara
|
|
100
100
|
attempts_reporter = CapybaraScreenshotDiff::AttemptsReporter.new(snapshot, @comparison_options, {wait: wait, stability_time_limit: stability_time_limit})
|
101
101
|
|
102
102
|
# TODO: Move fail to the queue after tests passed
|
103
|
-
|
103
|
+
raise CapybaraScreenshotDiff::UnstableImage, attempts_reporter.generate
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
@@ -35,26 +35,6 @@ module Capybara
|
|
35
35
|
@screenshot_group = nil
|
36
36
|
@screenshot_section = nil
|
37
37
|
@test_screenshot_errors = nil
|
38
|
-
@test_screenshots = []
|
39
|
-
end
|
40
|
-
|
41
|
-
# Verifies that all scheduled screenshots do not show any unintended differences.
|
42
|
-
#
|
43
|
-
# @param screenshots [Array(Array(Array(String), String, ImageCompare))] The list of match screenshots jobs. Defaults to all screenshots taken during the test.
|
44
|
-
# @return [Array, nil] Returns an array of error messages if there are screenshot differences, otherwise nil.
|
45
|
-
# @note This method is typically called at the end of a test to assert all screenshots are as expected.
|
46
|
-
def verify_screenshots!(screenshots = @test_screenshots)
|
47
|
-
return unless ::Capybara::Screenshot.active? && ::Capybara::Screenshot::Diff.fail_on_difference
|
48
|
-
|
49
|
-
test_screenshot_errors = screenshots.map do |caller, name, compare|
|
50
|
-
assert_image_not_changed(caller, name, compare)
|
51
|
-
end
|
52
|
-
|
53
|
-
test_screenshot_errors.compact!
|
54
|
-
|
55
|
-
test_screenshot_errors.presence
|
56
|
-
ensure
|
57
|
-
screenshots.clear
|
58
38
|
end
|
59
39
|
|
60
40
|
# Builds the full name for a screenshot, incorporating counters and group names for uniqueness.
|
@@ -83,8 +63,9 @@ module Capybara
|
|
83
63
|
|
84
64
|
def screenshot_group(name)
|
85
65
|
@screenshot_group = name.to_s
|
86
|
-
@screenshot_counter = @screenshot_group.
|
87
|
-
|
66
|
+
@screenshot_counter = (@screenshot_group.nil? || @screenshot_group.empty?) ? nil : 0
|
67
|
+
name_present = !(name.nil? || name.empty?)
|
68
|
+
return unless Screenshot.active? && name_present
|
88
69
|
|
89
70
|
FileUtils.rm_rf screenshot_dir
|
90
71
|
end
|
@@ -97,14 +78,14 @@ module Capybara
|
|
97
78
|
# @param job [Array(Array(String), String, ImageCompare)] The job to be scheduled, consisting of the caller context, screenshot name, and comparison object.
|
98
79
|
# @return [Boolean] Always returns true, indicating the job was successfully scheduled.
|
99
80
|
def schedule_match_job(job)
|
100
|
-
(
|
81
|
+
CapybaraScreenshotDiff.add_assertion(job)
|
101
82
|
true
|
102
83
|
end
|
103
84
|
|
104
85
|
def group_parts
|
105
86
|
parts = []
|
106
|
-
parts << @screenshot_section
|
107
|
-
parts << @screenshot_group
|
87
|
+
parts << @screenshot_section unless @screenshot_section.nil? || @screenshot_section.empty?
|
88
|
+
parts << @screenshot_group unless @screenshot_group.nil? || @screenshot_group.empty?
|
108
89
|
parts
|
109
90
|
end
|
110
91
|
|
@@ -120,13 +101,18 @@ module Capybara
|
|
120
101
|
def screenshot(name, skip_stack_frames: 0, **options)
|
121
102
|
return false unless Screenshot.active?
|
122
103
|
|
104
|
+
# setup
|
123
105
|
screenshot_full_name = build_full_name(name)
|
124
|
-
job = build_screenshot_matches_job(screenshot_full_name, options)
|
125
106
|
|
126
|
-
|
127
|
-
|
107
|
+
# exercise
|
108
|
+
match_changes_job = build_screenshot_matches_job(screenshot_full_name, options)
|
109
|
+
|
110
|
+
# verify
|
111
|
+
backtrace = caller(skip_stack_frames + 1).reject { |l| l =~ /gems\/(activesupport|minitest|railties)/ }
|
112
|
+
|
113
|
+
unless match_changes_job
|
128
114
|
if Screenshot::Diff.fail_if_new
|
129
|
-
_raise_error(<<-ERROR.strip_heredoc,
|
115
|
+
_raise_error(<<-ERROR.strip_heredoc, backtrace)
|
130
116
|
No existing screenshot found for #{screenshot_full_name}!
|
131
117
|
To stop seeing this error disable by `Capybara::Screenshot::Diff.fail_if_new=false`
|
132
118
|
ERROR
|
@@ -135,39 +121,26 @@ module Capybara
|
|
135
121
|
return false
|
136
122
|
end
|
137
123
|
|
138
|
-
|
124
|
+
match_changes_job.prepend(backtrace)
|
139
125
|
|
140
126
|
if Screenshot::Diff.delayed
|
141
|
-
schedule_match_job(
|
127
|
+
schedule_match_job(match_changes_job)
|
142
128
|
else
|
143
|
-
|
144
|
-
_raise_error(error_msg, caller(2)) if error_msg
|
129
|
+
invoke_match_job(match_changes_job)
|
145
130
|
end
|
146
131
|
end
|
147
132
|
|
148
|
-
|
149
|
-
#
|
150
|
-
# @param caller [Array(String)] The caller context, used for error reporting.
|
151
|
-
# @param name [String] The name of the screenshot being verified.
|
152
|
-
# @param comparison [Object] The comparison object containing the result and details of the comparison.
|
153
|
-
# @return [String, nil] Returns an error message if the screenshot differs from the baseline, otherwise nil.
|
154
|
-
# @note This method is used internally to verify individual screenshots.
|
155
|
-
def assert_image_not_changed(caller, name, comparison)
|
156
|
-
result = comparison.different?
|
157
|
-
|
158
|
-
# Cleanup after comparisons
|
159
|
-
if !result && comparison.base_image_path.exist?
|
160
|
-
FileUtils.mv(comparison.base_image_path, comparison.image_path, force: true)
|
161
|
-
elsif !comparison.dimensions_changed?
|
162
|
-
FileUtils.rm_rf(comparison.base_image_path)
|
163
|
-
end
|
133
|
+
private
|
164
134
|
|
165
|
-
|
135
|
+
def invoke_match_job(job)
|
136
|
+
error_msg = CapybaraScreenshotDiff::ScreenshotAssertion.from(job).validate
|
166
137
|
|
167
|
-
|
168
|
-
|
138
|
+
if error_msg
|
139
|
+
_raise_error(error_msg, job[0])
|
140
|
+
end
|
169
141
|
|
170
|
-
|
142
|
+
true
|
143
|
+
end
|
171
144
|
|
172
145
|
def _raise_error(error_msg, backtrace)
|
173
146
|
raise CapybaraScreenshotDiff::ExpectationNotMet.new(error_msg).tap { _1.set_backtrace(backtrace) }
|
@@ -6,7 +6,5 @@ World(::CapybaraScreenshotDiff::DSL)
|
|
6
6
|
|
7
7
|
Before do
|
8
8
|
Capybara::Screenshot::Diff.delayed = false
|
9
|
-
|
10
|
-
Capybara::Screenshot::BrowserHelpers.resize_to(Capybara::Screenshot.window_size)
|
11
|
-
end
|
9
|
+
Capybara::Screenshot::BrowserHelpers.resize_window_if_needed
|
12
10
|
end
|
@@ -2,10 +2,17 @@
|
|
2
2
|
|
3
3
|
require "capybara_screenshot_diff"
|
4
4
|
require "capybara/screenshot/diff/test_methods"
|
5
|
+
require_relative "screenshot_assertion"
|
5
6
|
|
6
7
|
module CapybaraScreenshotDiff
|
7
8
|
module DSL
|
8
9
|
include Capybara::DSL
|
9
10
|
include Capybara::Screenshot::Diff::TestMethods
|
11
|
+
|
12
|
+
alias_method :_screenshot, :screenshot
|
13
|
+
def screenshot(name, **args)
|
14
|
+
assertion = CapybaraScreenshotDiff::ScreenshotAssertion.new(name, **args) { _screenshot(name, **args) }
|
15
|
+
CapybaraScreenshotDiff.add_assertion(assertion)
|
16
|
+
end
|
10
17
|
end
|
11
18
|
end
|
@@ -20,29 +20,29 @@ module CapybaraScreenshotDiff
|
|
20
20
|
include ::CapybaraScreenshotDiff::DSL
|
21
21
|
|
22
22
|
def screenshot(*args, skip_stack_frames: 0, **opts)
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
self.assertions += 1
|
24
|
+
|
25
|
+
super(*args, skip_stack_frames: skip_stack_frames + 3, **opts)
|
26
|
+
rescue ::CapybaraScreenshotDiff::ExpectationNotMet => e
|
27
|
+
raise ::Minitest::Assertion, e.message
|
26
28
|
end
|
27
29
|
|
28
30
|
alias_method :assert_matches_screenshot, :screenshot
|
29
31
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
32
|
+
def setup
|
33
|
+
super
|
34
|
+
::Capybara::Screenshot::BrowserHelpers.resize_window_if_needed
|
35
|
+
end
|
36
|
+
|
37
|
+
def before_teardown
|
38
|
+
super
|
39
|
+
CapybaraScreenshotDiff.verify
|
40
|
+
rescue CapybaraScreenshotDiff::ExpectationNotMet => e
|
41
|
+
assertion = ::Minitest::Assertion.new(e)
|
42
|
+
assertion.set_backtrace []
|
43
|
+
failures << assertion
|
44
|
+
ensure
|
45
|
+
CapybaraScreenshotDiff.reset
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -13,20 +13,24 @@ RSpec::Matchers.define :match_screenshot do |name, **options|
|
|
13
13
|
end
|
14
14
|
|
15
15
|
RSpec.configure do |config|
|
16
|
-
config.include
|
17
|
-
config.include
|
16
|
+
config.include CapybaraScreenshotDiff::DSL, type: :feature
|
17
|
+
config.include CapybaraScreenshotDiff::DSL, type: :system
|
18
18
|
|
19
|
-
config.
|
20
|
-
if self.class.include?(
|
21
|
-
|
22
|
-
# TODO: Use rspec/mock approach to postpone verification
|
23
|
-
raise ::CapybaraScreenshotDiff::ExpectationNotMet, errors.join("\n") if errors && !errors.empty?
|
19
|
+
config.before do
|
20
|
+
if self.class.include?(CapybaraScreenshotDiff::DSL)
|
21
|
+
Capybara::Screenshot::BrowserHelpers.resize_window_if_needed
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
|
-
config.
|
28
|
-
if self.class.include?(
|
29
|
-
|
25
|
+
config.after do
|
26
|
+
if self.class.include?(CapybaraScreenshotDiff::DSL)
|
27
|
+
begin
|
28
|
+
CapybaraScreenshotDiff.verify
|
29
|
+
rescue CapybaraScreenshotDiff::ExpectationNotMet => e
|
30
|
+
raise RSpec::Expectations::ExpectationNotMetError, e.message
|
31
|
+
ensure
|
32
|
+
CapybaraScreenshotDiff.reset
|
33
|
+
end
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
module CapybaraScreenshotDiff
|
6
|
+
class ScreenshotAssertion
|
7
|
+
attr_reader :name, :args
|
8
|
+
attr_accessor :compare, :caller
|
9
|
+
|
10
|
+
def initialize(name, **args, &block)
|
11
|
+
@name = name
|
12
|
+
@args = args
|
13
|
+
|
14
|
+
yield(self) if block_given?
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from(screenshot_job)
|
18
|
+
return screenshot_job if screenshot_job.is_a?(ScreenshotAssertion)
|
19
|
+
|
20
|
+
caller, name, compare = screenshot_job
|
21
|
+
ScreenshotAssertion.new(name).tap do |it|
|
22
|
+
it.caller = caller
|
23
|
+
it.compare = compare
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate
|
28
|
+
return unless compare
|
29
|
+
|
30
|
+
self.class.assert_image_not_changed(caller, name, compare)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Verifies that all scheduled screenshots do not show any unintended differences.
|
34
|
+
#
|
35
|
+
# @param screenshots [Array(Array(Array(String), String, ImageCompare))] The list of match screenshots jobs. Defaults to all screenshots taken during the test.
|
36
|
+
# @return [Array, nil] Returns an array of error messages if there are screenshot differences, otherwise nil.
|
37
|
+
# @note This method is typically called at the end of a test to assert all screenshots are as expected.
|
38
|
+
def self.verify_screenshots!(screenshots)
|
39
|
+
return unless ::Capybara::Screenshot.active? && ::Capybara::Screenshot::Diff.fail_on_difference
|
40
|
+
|
41
|
+
test_screenshot_errors = screenshots.map do |assertion|
|
42
|
+
assertion.validate
|
43
|
+
end
|
44
|
+
|
45
|
+
test_screenshot_errors.compact!
|
46
|
+
|
47
|
+
test_screenshot_errors.empty? ? nil : test_screenshot_errors
|
48
|
+
ensure
|
49
|
+
screenshots&.clear
|
50
|
+
end
|
51
|
+
|
52
|
+
# Asserts that an image has not changed compared to its baseline.
|
53
|
+
#
|
54
|
+
# @param backtrace [Array(String)] The caller context, used for error reporting.
|
55
|
+
# @param name [String] The name of the screenshot being verified.
|
56
|
+
# @param comparison [Object] The comparison object containing the result and details of the comparison.
|
57
|
+
# @return [String, nil] Returns an error message if the screenshot differs from the baseline, otherwise nil.
|
58
|
+
# @note This method is used internally to verify individual screenshots.
|
59
|
+
def self.assert_image_not_changed(backtrace, name, comparison)
|
60
|
+
result = comparison.different?
|
61
|
+
|
62
|
+
# Cleanup after comparisons
|
63
|
+
if !result && comparison.base_image_path.exist?
|
64
|
+
FileUtils.mv(comparison.base_image_path, comparison.image_path, force: true)
|
65
|
+
elsif !comparison.dimensions_changed?
|
66
|
+
FileUtils.rm_rf(comparison.base_image_path)
|
67
|
+
end
|
68
|
+
|
69
|
+
return unless result
|
70
|
+
|
71
|
+
"Screenshot does not match for '#{name}': #{comparison.error_message}\n#{backtrace.join("\n")}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class AssertionRegistry
|
76
|
+
attr_reader :assertions
|
77
|
+
|
78
|
+
def initialize
|
79
|
+
@assertions = []
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_assertion(assertion)
|
83
|
+
assertion = ScreenshotAssertion.from(assertion)
|
84
|
+
return unless assertion.compare
|
85
|
+
|
86
|
+
@assertions.push(assertion)
|
87
|
+
|
88
|
+
assertion
|
89
|
+
end
|
90
|
+
|
91
|
+
def assertions_present?
|
92
|
+
!@assertions.empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
def verify(screenshots = CapybaraScreenshotDiff.assertions)
|
96
|
+
result = ScreenshotAssertion.verify_screenshots!(screenshots)
|
97
|
+
|
98
|
+
raise CapybaraScreenshotDiff::ExpectationNotMet, result.join("\n\n") if result
|
99
|
+
end
|
100
|
+
|
101
|
+
def failed_assertions
|
102
|
+
assertions.select { |screenshot_assert| screenshot_assert.compare&.different? }
|
103
|
+
end
|
104
|
+
|
105
|
+
def reset
|
106
|
+
@assertions.clear
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
module CapybaraScreenshotDiff
|
112
|
+
class << self
|
113
|
+
require "forwardable"
|
114
|
+
extend Forwardable
|
115
|
+
|
116
|
+
def registry
|
117
|
+
Thread.current[:capybara_screenshot_diff_registry] ||= AssertionRegistry.new
|
118
|
+
end
|
119
|
+
|
120
|
+
def_delegator :registry, :add_assertion
|
121
|
+
def_delegator :registry, :assertions
|
122
|
+
def_delegator :registry, :assertions_present?
|
123
|
+
def_delegator :registry, :failed_assertions
|
124
|
+
def_delegator :registry, :reset
|
125
|
+
def_delegator :registry, :verify
|
126
|
+
end
|
127
|
+
end
|
@@ -10,7 +10,11 @@ require "capybara/screenshot/diff/screenshoter"
|
|
10
10
|
require "capybara/screenshot/diff/reporters/default"
|
11
11
|
|
12
12
|
module CapybaraScreenshotDiff
|
13
|
-
class
|
13
|
+
class CapybaraScreenshotDiffError < StandardError; end
|
14
|
+
|
15
|
+
class ExpectationNotMet < CapybaraScreenshotDiffError; end
|
16
|
+
|
17
|
+
class UnstableImage < CapybaraScreenshotDiffError; end
|
14
18
|
end
|
15
19
|
|
16
20
|
module Capybara
|
@@ -49,7 +53,7 @@ module Capybara
|
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
52
|
-
# Module to track
|
56
|
+
# Module to track screenshot changes
|
53
57
|
module Diff
|
54
58
|
mattr_accessor(:delayed) { true }
|
55
59
|
mattr_accessor :area_size_limit
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara-screenshot-diff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.10.
|
4
|
+
version: 1.10.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uwe Kubosch
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: actionpack
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- lib/capybara_screenshot_diff/dsl.rb
|
89
89
|
- lib/capybara_screenshot_diff/minitest.rb
|
90
90
|
- lib/capybara_screenshot_diff/rspec.rb
|
91
|
+
- lib/capybara_screenshot_diff/screenshot_assertion.rb
|
91
92
|
- lib/capybara_screenshot_diff/snap.rb
|
92
93
|
- lib/capybara_screenshot_diff/snap_manager.rb
|
93
94
|
homepage: https://github.com/donv/capybara-screenshot-diff
|
@@ -109,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
110
|
- !ruby/object:Gem::Version
|
110
111
|
version: '0'
|
111
112
|
requirements: []
|
112
|
-
rubygems_version: 3.6.
|
113
|
+
rubygems_version: 3.6.7
|
113
114
|
specification_version: 4
|
114
115
|
summary: Track your GUI changes with diff assertions
|
115
116
|
test_files: []
|