capybara-screenshot-diff 1.12.0 → 1.13.0
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/CHANGELOG.md +13 -0
- data/CODE_OF_CONDUCT.md +129 -0
- data/docs/RELEASE_PREP.md +15 -31
- data/docs/architecture.md +270 -0
- data/docs/ci-integration.md +107 -77
- data/docs/configuration.md +16 -0
- data/docs/images/snap_diff_annotated.png +0 -0
- data/docs/migration-guide.md +286 -0
- data/docs/organization.md +1 -23
- data/lib/capybara/screenshot/diff/screenshot_matcher.rb +15 -1
- data/lib/capybara/screenshot/diff/version.rb +1 -1
- data/lib/capybara_screenshot_diff/cucumber.rb +9 -0
- data/lib/capybara_screenshot_diff/dsl.rb +28 -7
- data/lib/capybara_screenshot_diff/minitest.rb +6 -3
- data/lib/capybara_screenshot_diff/rspec.rb +8 -2
- data/lib/capybara_screenshot_diff/screenshot_assertion.rb +14 -1
- data/lib/capybara_screenshot_diff.rb +1 -0
- metadata +6 -2
|
@@ -25,7 +25,7 @@ module CapybaraScreenshotDiff
|
|
|
25
25
|
screenshot_namer.group = name
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
# Takes a screenshot and
|
|
28
|
+
# Takes a screenshot and compares it against a baseline image.
|
|
29
29
|
#
|
|
30
30
|
# The method follows a layered optimization strategy for comparison:
|
|
31
31
|
# 1. First checks if screenshot functionality is active
|
|
@@ -53,7 +53,7 @@ module CapybaraScreenshotDiff
|
|
|
53
53
|
# @raise [CapybaraScreenshotDiff::ExpectationNotMet] If comparison fails and immediate validation is enabled.
|
|
54
54
|
# @raise [CapybaraScreenshotDiff::UnstableImage] If the image comparison is unstable.
|
|
55
55
|
# @raise [CapybaraScreenshotDiff::WindowSizeMismatchError] If the window size doesn't match expectations.
|
|
56
|
-
def
|
|
56
|
+
def assert_matches_screenshot(name, skip_stack_frames: 0, **options)
|
|
57
57
|
return false unless Capybara::Screenshot.active?
|
|
58
58
|
|
|
59
59
|
# Get the full name with section and group information
|
|
@@ -76,15 +76,36 @@ module CapybaraScreenshotDiff
|
|
|
76
76
|
true
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
#
|
|
80
|
-
# @
|
|
81
|
-
|
|
79
|
+
# Convenience wrapper around {#assert_matches_screenshot} and {#capture_screenshot}.
|
|
80
|
+
# @param compare [Boolean] When false, only captures the screenshot without comparing it to a baseline.
|
|
81
|
+
# @see #assert_matches_screenshot
|
|
82
|
+
# @see #capture_screenshot
|
|
83
|
+
def screenshot(name, skip_stack_frames: 0, compare: true, **options)
|
|
84
|
+
if compare
|
|
85
|
+
assert_matches_screenshot(name, skip_stack_frames: skip_stack_frames + 1, **options)
|
|
86
|
+
else
|
|
87
|
+
capture_screenshot(name, **options)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Captures a screenshot without comparing it to a baseline.
|
|
92
|
+
# @param name [String] The base name of the screenshot, used to generate the filename.
|
|
93
|
+
# @param options [Hash] Additional options for taking the screenshot. See {#assert_matches_screenshot}.
|
|
94
|
+
# @return [Boolean] True if the screenshot was successfully captured.
|
|
95
|
+
def capture_screenshot(name, **options)
|
|
96
|
+
return false unless Capybara::Screenshot.active?
|
|
97
|
+
|
|
98
|
+
full_name = CapybaraScreenshotDiff.screenshot_namer.full_name(name)
|
|
99
|
+
Capybara::Screenshot::Diff::ScreenshotMatcher.new(full_name, options).capture
|
|
100
|
+
|
|
101
|
+
true
|
|
102
|
+
end
|
|
82
103
|
|
|
83
104
|
# Asserts the current page has no visual changes from the baseline.
|
|
84
105
|
# Override in your base test class to add project-specific behavior
|
|
85
106
|
# (e.g., waiting for Turbo, default skip areas).
|
|
86
107
|
def assert_no_screenshot_changes(name, skip_stack_frames: 0, **opts)
|
|
87
|
-
|
|
108
|
+
assert_matches_screenshot(name, skip_stack_frames: skip_stack_frames + 1, **opts)
|
|
88
109
|
end
|
|
89
110
|
|
|
90
111
|
private
|
|
@@ -96,7 +117,7 @@ module CapybaraScreenshotDiff
|
|
|
96
117
|
#
|
|
97
118
|
# @param name [String] The full name of the screenshot, including any section/group context.
|
|
98
119
|
# @param options [Hash] Options for screenshot taking and comparison.
|
|
99
|
-
# See {#
|
|
120
|
+
# See {#assert_matches_screenshot} for available options.
|
|
100
121
|
# @param skip_stack_frames [Integer] Number of stack frames to skip for error reporting.
|
|
101
122
|
# @return [ScreenshotAssertion, nil] The assertion object or nil if no assertion is needed.
|
|
102
123
|
# @see ScreenshotAssertion
|
|
@@ -19,7 +19,7 @@ module CapybaraScreenshotDiff
|
|
|
19
19
|
module Assertions
|
|
20
20
|
include ::CapybaraScreenshotDiff::DSL
|
|
21
21
|
|
|
22
|
-
def
|
|
22
|
+
def assert_matches_screenshot(*args, skip_stack_frames: 0, **opts)
|
|
23
23
|
self.assertions += 1
|
|
24
24
|
|
|
25
25
|
super(*args, skip_stack_frames: skip_stack_frames + 1, **opts)
|
|
@@ -27,8 +27,6 @@ module CapybaraScreenshotDiff
|
|
|
27
27
|
raise ::Minitest::Assertion, e.message
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
alias_method :assert_matches_screenshot, :screenshot
|
|
31
|
-
|
|
32
30
|
def setup
|
|
33
31
|
super
|
|
34
32
|
::Capybara::Screenshot::BrowserHelpers.resize_window_if_needed
|
|
@@ -37,6 +35,11 @@ module CapybaraScreenshotDiff
|
|
|
37
35
|
def before_teardown
|
|
38
36
|
super
|
|
39
37
|
CapybaraScreenshotDiff.verify
|
|
38
|
+
|
|
39
|
+
if ::Capybara::Screenshot::Diff.pending_if_new && CapybaraScreenshotDiff.new_screenshots_present?
|
|
40
|
+
names = CapybaraScreenshotDiff.new_screenshots
|
|
41
|
+
skip "No baseline for: #{names.join(", ")}. Commit the captured screenshots to record them."
|
|
42
|
+
end
|
|
40
43
|
rescue CapybaraScreenshotDiff::ExpectationNotMet => e
|
|
41
44
|
assertion = ::Minitest::Assertion.new(e)
|
|
42
45
|
assertion.set_backtrace(e.backtrace)
|
|
@@ -7,7 +7,7 @@ RSpec::Matchers.define :match_screenshot do |name, **options|
|
|
|
7
7
|
description { "match screenshot '#{name}'" }
|
|
8
8
|
|
|
9
9
|
match do |_page|
|
|
10
|
-
|
|
10
|
+
assert_matches_screenshot(name, **options)
|
|
11
11
|
true
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -30,10 +30,16 @@ RSpec.configure do |config|
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
config.after do
|
|
33
|
+
config.after do |example|
|
|
34
34
|
if self.class.include?(CapybaraScreenshotDiff::DSL)
|
|
35
35
|
begin
|
|
36
36
|
CapybaraScreenshotDiff.verify
|
|
37
|
+
|
|
38
|
+
# Never mask a real failure with a pending marker.
|
|
39
|
+
if example.exception.nil? && Capybara::Screenshot::Diff.pending_if_new && CapybaraScreenshotDiff.new_screenshots_present?
|
|
40
|
+
names = CapybaraScreenshotDiff.new_screenshots
|
|
41
|
+
skip "No baseline for: #{names.join(", ")}. Commit the captured screenshots to record them."
|
|
42
|
+
end
|
|
37
43
|
rescue CapybaraScreenshotDiff::ExpectationNotMet => e
|
|
38
44
|
raise RSpec::Expectations::ExpectationNotMetError.new(e.message).tap { |ex| ex.set_backtrace(e.backtrace) }
|
|
39
45
|
ensure
|
|
@@ -65,10 +65,11 @@ module CapybaraScreenshotDiff
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
class AssertionRegistry
|
|
68
|
-
attr_reader :assertions, :screenshot_namer
|
|
68
|
+
attr_reader :assertions, :screenshot_namer, :new_screenshots
|
|
69
69
|
|
|
70
70
|
def initialize
|
|
71
71
|
@assertions = []
|
|
72
|
+
@new_screenshots = []
|
|
72
73
|
@screenshot_namer = CapybaraScreenshotDiff::ScreenshotNamer.new
|
|
73
74
|
end
|
|
74
75
|
|
|
@@ -84,6 +85,14 @@ module CapybaraScreenshotDiff
|
|
|
84
85
|
!@assertions.empty?
|
|
85
86
|
end
|
|
86
87
|
|
|
88
|
+
def record_new_screenshot(name)
|
|
89
|
+
@new_screenshots.push(name)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def new_screenshots_present?
|
|
93
|
+
!@new_screenshots.empty?
|
|
94
|
+
end
|
|
95
|
+
|
|
87
96
|
def verify(screenshots = CapybaraScreenshotDiff.assertions)
|
|
88
97
|
return unless ::Capybara::Screenshot.active? && ::Capybara::Screenshot::Diff.fail_on_difference
|
|
89
98
|
|
|
@@ -102,6 +111,7 @@ module CapybaraScreenshotDiff
|
|
|
102
111
|
|
|
103
112
|
def reset
|
|
104
113
|
@assertions.clear
|
|
114
|
+
@new_screenshots.clear
|
|
105
115
|
@screenshot_namer = CapybaraScreenshotDiff::ScreenshotNamer.new
|
|
106
116
|
end
|
|
107
117
|
end
|
|
@@ -120,6 +130,9 @@ module CapybaraScreenshotDiff
|
|
|
120
130
|
def_delegator :registry, :assertions
|
|
121
131
|
def_delegator :registry, :assertions_present?
|
|
122
132
|
def_delegator :registry, :failed_assertions
|
|
133
|
+
def_delegator :registry, :record_new_screenshot
|
|
134
|
+
def_delegator :registry, :new_screenshots
|
|
135
|
+
def_delegator :registry, :new_screenshots_present?
|
|
123
136
|
def reset
|
|
124
137
|
notify_reporters(registry.assertions)
|
|
125
138
|
registry.reset
|
|
@@ -65,6 +65,7 @@ module Capybara
|
|
|
65
65
|
mattr_accessor(:delayed) { true }
|
|
66
66
|
mattr_accessor :area_size_limit
|
|
67
67
|
mattr_accessor(:fail_if_new) { !ENV["CI"].nil? && !ENV["CI"].empty? }
|
|
68
|
+
mattr_accessor(:pending_if_new) { false }
|
|
68
69
|
mattr_accessor(:fail_on_difference) { true }
|
|
69
70
|
mattr_accessor :color_distance_limit
|
|
70
71
|
mattr_accessor(:enabled) { true }
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capybara-screenshot-diff
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Uwe Kubosch
|
|
@@ -77,17 +77,21 @@ extensions: []
|
|
|
77
77
|
extra_rdoc_files: []
|
|
78
78
|
files:
|
|
79
79
|
- CHANGELOG.md
|
|
80
|
+
- CODE_OF_CONDUCT.md
|
|
80
81
|
- LICENSE.txt
|
|
81
82
|
- Rakefile
|
|
82
83
|
- capybara-screenshot-diff.gemspec
|
|
83
84
|
- docs/RELEASE_PREP.md
|
|
84
85
|
- docs/UPGRADING.md
|
|
86
|
+
- docs/architecture.md
|
|
85
87
|
- docs/ci-integration.md
|
|
86
88
|
- docs/configuration.md
|
|
87
89
|
- docs/docker-testing.md
|
|
88
90
|
- docs/drivers.md
|
|
89
91
|
- docs/framework-setup.md
|
|
92
|
+
- docs/images/snap_diff_annotated.png
|
|
90
93
|
- docs/images/snap_diff_web_ui.png
|
|
94
|
+
- docs/migration-guide.md
|
|
91
95
|
- docs/organization.md
|
|
92
96
|
- docs/reporters.md
|
|
93
97
|
- docs/thread_safety.md
|
|
@@ -149,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
149
153
|
- !ruby/object:Gem::Version
|
|
150
154
|
version: '0'
|
|
151
155
|
requirements: []
|
|
152
|
-
rubygems_version: 4.0.
|
|
156
|
+
rubygems_version: 4.0.16
|
|
153
157
|
specification_version: 4
|
|
154
158
|
summary: Track your GUI changes with diff assertions
|
|
155
159
|
test_files: []
|