rspec-expectations 2.14.0 → 3.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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +1 -1
- data/Changelog.md +976 -25
- data/{License.txt → LICENSE.md} +5 -3
- data/README.md +162 -26
- data/lib/rspec/expectations/block_snippet_extractor.rb +253 -0
- data/lib/rspec/expectations/configuration.rb +230 -0
- data/lib/rspec/expectations/expectation_target.rb +127 -51
- data/lib/rspec/expectations/fail_with.rb +17 -57
- data/lib/rspec/expectations/failure_aggregator.rb +229 -0
- data/lib/rspec/expectations/handler.rb +146 -32
- data/lib/rspec/expectations/minitest_integration.rb +58 -0
- data/lib/rspec/expectations/syntax.rb +68 -100
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/expectations.rb +58 -23
- data/lib/rspec/matchers/aliased_matcher.rb +116 -0
- data/lib/rspec/matchers/built_in/all.rb +86 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +191 -20
- data/lib/rspec/matchers/built_in/be.rb +114 -114
- data/lib/rspec/matchers/built_in/be_between.rb +77 -0
- data/lib/rspec/matchers/built_in/be_instance_of.rb +15 -4
- data/lib/rspec/matchers/built_in/be_kind_of.rb +10 -1
- data/lib/rspec/matchers/built_in/be_within.rb +35 -18
- data/lib/rspec/matchers/built_in/change.rb +389 -80
- data/lib/rspec/matchers/built_in/compound.rb +290 -0
- data/lib/rspec/matchers/built_in/contain_exactly.rb +310 -0
- data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
- data/lib/rspec/matchers/built_in/cover.rb +3 -0
- data/lib/rspec/matchers/built_in/eq.rb +30 -8
- data/lib/rspec/matchers/built_in/eql.rb +23 -8
- data/lib/rspec/matchers/built_in/equal.rb +55 -22
- data/lib/rspec/matchers/built_in/exist.rb +74 -10
- data/lib/rspec/matchers/built_in/has.rb +141 -22
- data/lib/rspec/matchers/built_in/have_attributes.rb +114 -0
- data/lib/rspec/matchers/built_in/include.rb +184 -32
- data/lib/rspec/matchers/built_in/match.rb +95 -1
- data/lib/rspec/matchers/built_in/operators.rb +128 -0
- data/lib/rspec/matchers/built_in/output.rb +207 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +192 -44
- data/lib/rspec/matchers/built_in/respond_to.rb +154 -28
- data/lib/rspec/matchers/built_in/satisfy.rb +39 -9
- data/lib/rspec/matchers/built_in/start_or_end_with.rb +94 -0
- data/lib/rspec/matchers/built_in/throw_symbol.rb +58 -14
- data/lib/rspec/matchers/built_in/yield.rb +240 -161
- data/lib/rspec/matchers/built_in.rb +47 -33
- data/lib/rspec/matchers/composable.rb +171 -0
- data/lib/rspec/matchers/dsl.rb +531 -10
- data/lib/rspec/matchers/english_phrasing.rb +58 -0
- data/lib/rspec/matchers/fail_matchers.rb +42 -0
- data/lib/rspec/matchers/generated_descriptions.rb +14 -8
- data/lib/rspec/matchers/matcher_delegator.rb +61 -0
- data/lib/rspec/matchers/matcher_protocol.rb +105 -0
- data/lib/rspec/matchers/multi_matcher_diff.rb +82 -0
- data/lib/rspec/matchers.rb +520 -173
- data.tar.gz.sig +0 -0
- metadata +141 -242
- metadata.gz.sig +2 -0
- data/features/README.md +0 -48
- data/features/Upgrade.md +0 -53
- data/features/built_in_matchers/README.md +0 -90
- data/features/built_in_matchers/be.feature +0 -175
- data/features/built_in_matchers/be_within.feature +0 -48
- data/features/built_in_matchers/cover.feature +0 -47
- data/features/built_in_matchers/end_with.feature +0 -48
- data/features/built_in_matchers/equality.feature +0 -139
- data/features/built_in_matchers/exist.feature +0 -45
- data/features/built_in_matchers/expect_change.feature +0 -59
- data/features/built_in_matchers/expect_error.feature +0 -144
- data/features/built_in_matchers/have.feature +0 -109
- data/features/built_in_matchers/include.feature +0 -174
- data/features/built_in_matchers/match.feature +0 -52
- data/features/built_in_matchers/operators.feature +0 -227
- data/features/built_in_matchers/predicates.feature +0 -137
- data/features/built_in_matchers/respond_to.feature +0 -84
- data/features/built_in_matchers/satisfy.feature +0 -33
- data/features/built_in_matchers/start_with.feature +0 -48
- data/features/built_in_matchers/throw_symbol.feature +0 -91
- data/features/built_in_matchers/types.feature +0 -116
- data/features/built_in_matchers/yield.feature +0 -161
- data/features/custom_matchers/access_running_example.feature +0 -53
- data/features/custom_matchers/define_diffable_matcher.feature +0 -27
- data/features/custom_matchers/define_matcher.feature +0 -368
- data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
- data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
- data/features/customized_message.feature +0 -22
- data/features/diffing.feature +0 -85
- data/features/implicit_docstrings.feature +0 -52
- data/features/step_definitions/additional_cli_steps.rb +0 -22
- data/features/support/env.rb +0 -14
- data/features/syntax_configuration.feature +0 -71
- data/features/test_frameworks/test_unit.feature +0 -44
- data/lib/rspec/expectations/deprecation.rb +0 -17
- data/lib/rspec/expectations/differ.rb +0 -133
- data/lib/rspec/expectations/errors.rb +0 -9
- data/lib/rspec/expectations/extensions/array.rb +0 -9
- data/lib/rspec/expectations/extensions/object.rb +0 -29
- data/lib/rspec/expectations/extensions.rb +0 -2
- data/lib/rspec/matchers/be_close.rb +0 -9
- data/lib/rspec/matchers/built_in/have.rb +0 -124
- data/lib/rspec/matchers/built_in/match_array.rb +0 -51
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +0 -48
- data/lib/rspec/matchers/compatibility.rb +0 -14
- data/lib/rspec/matchers/configuration.rb +0 -108
- data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
- data/lib/rspec/matchers/matcher.rb +0 -300
- data/lib/rspec/matchers/method_missing.rb +0 -12
- data/lib/rspec/matchers/operator_matcher.rb +0 -109
- data/lib/rspec/matchers/pretty.rb +0 -70
- data/lib/rspec/matchers/test_unit_integration.rb +0 -11
- data/lib/rspec-expectations.rb +0 -1
- data/spec/rspec/expectations/differ_spec.rb +0 -192
- data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
- data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
- data/spec/rspec/expectations/fail_with_spec.rb +0 -114
- data/spec/rspec/expectations/handler_spec.rb +0 -227
- data/spec/rspec/expectations/syntax_spec.rb +0 -139
- data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
- data/spec/rspec/matchers/be_close_spec.rb +0 -22
- data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
- data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
- data/spec/rspec/matchers/be_spec.rb +0 -516
- data/spec/rspec/matchers/be_within_spec.rb +0 -137
- data/spec/rspec/matchers/change_spec.rb +0 -553
- data/spec/rspec/matchers/configuration_spec.rb +0 -206
- data/spec/rspec/matchers/cover_spec.rb +0 -69
- data/spec/rspec/matchers/description_generation_spec.rb +0 -190
- data/spec/rspec/matchers/dsl_spec.rb +0 -57
- data/spec/rspec/matchers/eq_spec.rb +0 -60
- data/spec/rspec/matchers/eql_spec.rb +0 -41
- data/spec/rspec/matchers/equal_spec.rb +0 -78
- data/spec/rspec/matchers/exist_spec.rb +0 -124
- data/spec/rspec/matchers/has_spec.rb +0 -122
- data/spec/rspec/matchers/have_spec.rb +0 -455
- data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
- data/spec/rspec/matchers/include_spec.rb +0 -531
- data/spec/rspec/matchers/match_array_spec.rb +0 -194
- data/spec/rspec/matchers/match_spec.rb +0 -61
- data/spec/rspec/matchers/matcher_spec.rb +0 -471
- data/spec/rspec/matchers/matchers_spec.rb +0 -37
- data/spec/rspec/matchers/method_missing_spec.rb +0 -28
- data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
- data/spec/rspec/matchers/raise_error_spec.rb +0 -485
- data/spec/rspec/matchers/respond_to_spec.rb +0 -292
- data/spec/rspec/matchers/satisfy_spec.rb +0 -44
- data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
- data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
- data/spec/rspec/matchers/yield_spec.rb +0 -514
- data/spec/spec_helper.rb +0 -54
- data/spec/support/classes.rb +0 -56
- data/spec/support/in_sub_process.rb +0 -38
- data/spec/support/matchers.rb +0 -22
- data/spec/support/ruby_version.rb +0 -10
- data/spec/support/shared_examples.rb +0 -13
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Matchers
|
5
|
+
module BuiltIn
|
6
|
+
# @api private
|
7
|
+
# Provides the implementation for `output`.
|
8
|
+
# Not intended to be instantiated directly.
|
9
|
+
class Output < BaseMatcher
|
10
|
+
def initialize(expected)
|
11
|
+
@expected = expected
|
12
|
+
@actual = ""
|
13
|
+
@block = nil
|
14
|
+
@stream_capturer = NullCapture
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?(block)
|
18
|
+
@block = block
|
19
|
+
return false unless Proc === block
|
20
|
+
@actual = @stream_capturer.capture(block)
|
21
|
+
@expected ? values_match?(@expected, @actual) : captured?
|
22
|
+
end
|
23
|
+
|
24
|
+
def does_not_match?(block)
|
25
|
+
!matches?(block) && Proc === block
|
26
|
+
end
|
27
|
+
|
28
|
+
# @api public
|
29
|
+
# Tells the matcher to match against stdout.
|
30
|
+
# Works only when the main Ruby process prints to stdout
|
31
|
+
def to_stdout
|
32
|
+
@stream_capturer = CaptureStdout
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
# @api public
|
37
|
+
# Tells the matcher to match against stderr.
|
38
|
+
# Works only when the main Ruby process prints to stderr
|
39
|
+
def to_stderr
|
40
|
+
@stream_capturer = CaptureStderr
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# @api public
|
45
|
+
# Tells the matcher to match against stdout.
|
46
|
+
# Works when subprocesses print to stdout as well.
|
47
|
+
# This is significantly (~30x) slower than `to_stdout`
|
48
|
+
def to_stdout_from_any_process
|
49
|
+
@stream_capturer = CaptureStreamToTempfile.new("stdout", $stdout)
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# @api public
|
54
|
+
# Tells the matcher to match against stderr.
|
55
|
+
# Works when subprocesses print to stderr as well.
|
56
|
+
# This is significantly (~30x) slower than `to_stderr`
|
57
|
+
def to_stderr_from_any_process
|
58
|
+
@stream_capturer = CaptureStreamToTempfile.new("stderr", $stderr)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api private
|
63
|
+
# @return [String]
|
64
|
+
def failure_message
|
65
|
+
"expected block to #{description}, but #{positive_failure_reason}"
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
# @return [String]
|
70
|
+
def failure_message_when_negated
|
71
|
+
"expected block to not #{description}, but #{negative_failure_reason}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# @api private
|
75
|
+
# @return [String]
|
76
|
+
def description
|
77
|
+
if @expected
|
78
|
+
"output #{description_of @expected} to #{@stream_capturer.name}"
|
79
|
+
else
|
80
|
+
"output to #{@stream_capturer.name}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @api private
|
85
|
+
# @return [Boolean]
|
86
|
+
def diffable?
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
# @api private
|
91
|
+
# Indicates this matcher matches against a block.
|
92
|
+
# @return [True]
|
93
|
+
def supports_block_expectations?
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
# @api private
|
98
|
+
# Indicates this matcher matches against a block only.
|
99
|
+
# @return [False]
|
100
|
+
def supports_value_expectations?
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def captured?
|
107
|
+
@actual.length > 0
|
108
|
+
end
|
109
|
+
|
110
|
+
def positive_failure_reason
|
111
|
+
return "was not a block" unless Proc === @block
|
112
|
+
return "output #{actual_output_description}" if @expected
|
113
|
+
"did not"
|
114
|
+
end
|
115
|
+
|
116
|
+
def negative_failure_reason
|
117
|
+
return "was not a block" unless Proc === @block
|
118
|
+
"output #{actual_output_description}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def actual_output_description
|
122
|
+
return "nothing" unless captured?
|
123
|
+
actual_formatted
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# @private
|
128
|
+
module NullCapture
|
129
|
+
def self.name
|
130
|
+
"some stream"
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.capture(_block)
|
134
|
+
raise "You must chain `to_stdout` or `to_stderr` off of the `output(...)` matcher."
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @private
|
139
|
+
module CaptureStdout
|
140
|
+
def self.name
|
141
|
+
'stdout'
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.capture(block)
|
145
|
+
captured_stream = StringIO.new
|
146
|
+
|
147
|
+
original_stream = $stdout
|
148
|
+
$stdout = captured_stream
|
149
|
+
|
150
|
+
block.call
|
151
|
+
|
152
|
+
captured_stream.string
|
153
|
+
ensure
|
154
|
+
$stdout = original_stream
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# @private
|
159
|
+
module CaptureStderr
|
160
|
+
def self.name
|
161
|
+
'stderr'
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.capture(block)
|
165
|
+
captured_stream = StringIO.new
|
166
|
+
|
167
|
+
original_stream = $stderr
|
168
|
+
$stderr = captured_stream
|
169
|
+
|
170
|
+
block.call
|
171
|
+
|
172
|
+
captured_stream.string
|
173
|
+
ensure
|
174
|
+
$stderr = original_stream
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# @private
|
179
|
+
class CaptureStreamToTempfile < Struct.new(:name, :stream)
|
180
|
+
def capture(block)
|
181
|
+
# We delay loading tempfile until it is actually needed because
|
182
|
+
# we want to minimize stdlibs loaded so that users who use a
|
183
|
+
# portion of the stdlib can't have passing specs while forgetting
|
184
|
+
# to load it themselves. `CaptureStreamToTempfile` is rarely used
|
185
|
+
# and `tempfile` pulls in a bunch of things (delegate, tmpdir,
|
186
|
+
# thread, fileutils, etc), so it's worth delaying it until this point.
|
187
|
+
require 'tempfile'
|
188
|
+
|
189
|
+
original_stream = stream.clone
|
190
|
+
captured_stream = Tempfile.new(name)
|
191
|
+
|
192
|
+
begin
|
193
|
+
captured_stream.sync = true
|
194
|
+
stream.reopen(captured_stream)
|
195
|
+
block.call
|
196
|
+
captured_stream.rewind
|
197
|
+
captured_stream.read
|
198
|
+
ensure
|
199
|
+
stream.reopen(original_stream)
|
200
|
+
captured_stream.close
|
201
|
+
captured_stream.unlink
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -1,56 +1,141 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
|
+
# @api private
|
5
|
+
# Provides the implementation for `raise_error`.
|
6
|
+
# Not intended to be instantiated directly.
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
8
|
+
# rubocop:disable Lint/RescueException
|
4
9
|
class RaiseError
|
5
|
-
|
10
|
+
include Composable
|
11
|
+
|
12
|
+
# Used as a sentinel value to be able to tell when the user did not pass an
|
13
|
+
# argument. We can't use `nil` for that because we need to warn when `nil` is
|
14
|
+
# passed in a different way. It's an Object, not a Module, since Module's `===`
|
15
|
+
# does not evaluate to true when compared to itself.
|
16
|
+
UndefinedValue = Object.new.freeze
|
17
|
+
|
18
|
+
def initialize(expected_error_or_message, expected_message, &block)
|
6
19
|
@block = block
|
7
20
|
@actual_error = nil
|
21
|
+
@warn_about_bare_error = UndefinedValue === expected_error_or_message
|
22
|
+
@warn_about_nil_error = expected_error_or_message.nil?
|
23
|
+
|
8
24
|
case expected_error_or_message
|
9
|
-
when
|
10
|
-
@expected_error
|
25
|
+
when nil, UndefinedValue
|
26
|
+
@expected_error = Exception
|
27
|
+
@expected_message = expected_message
|
28
|
+
when String
|
29
|
+
@expected_error = Exception
|
30
|
+
@expected_message = expected_error_or_message
|
11
31
|
else
|
12
|
-
@expected_error
|
32
|
+
@expected_error = expected_error_or_message
|
33
|
+
@expected_message = expected_message
|
13
34
|
end
|
14
35
|
end
|
15
36
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
# @api public
|
38
|
+
# Specifies the expected error message.
|
39
|
+
def with_message(expected_message)
|
40
|
+
raise_message_already_set if @expected_message
|
41
|
+
@warn_about_bare_error = false
|
42
|
+
@expected_message = expected_message
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
# rubocop:disable Metrics/MethodLength
|
47
|
+
# @private
|
48
|
+
def matches?(given_proc, negative_expectation=false, &block)
|
49
|
+
@given_proc = given_proc
|
50
|
+
@block ||= block
|
27
51
|
@raised_expected_error = false
|
28
52
|
@with_expected_message = false
|
29
53
|
@eval_block = false
|
30
54
|
@eval_block_passed = false
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
55
|
+
|
56
|
+
return false unless Proc === given_proc
|
57
|
+
|
35
58
|
begin
|
36
59
|
given_proc.call
|
37
60
|
rescue Exception => @actual_error
|
38
|
-
if @
|
61
|
+
if values_match?(@expected_error, @actual_error) ||
|
62
|
+
values_match?(@expected_error, actual_error_message)
|
39
63
|
@raised_expected_error = true
|
40
64
|
@with_expected_message = verify_message
|
41
65
|
end
|
42
66
|
end
|
43
67
|
|
44
68
|
unless negative_expectation
|
45
|
-
|
69
|
+
warn_about_bare_error! if warn_about_bare_error?
|
70
|
+
warn_about_nil_error! if warn_about_nil_error?
|
71
|
+
eval_block if ready_to_eval_block?
|
46
72
|
end
|
47
|
-
|
48
|
-
|
73
|
+
|
74
|
+
expectation_matched?
|
49
75
|
end
|
50
|
-
|
76
|
+
# rubocop:enable Metrics/MethodLength
|
51
77
|
|
78
|
+
# @private
|
52
79
|
def does_not_match?(given_proc)
|
53
|
-
!
|
80
|
+
warn_for_negative_false_positives!
|
81
|
+
!matches?(given_proc, :negative_expectation) && Proc === given_proc
|
82
|
+
end
|
83
|
+
|
84
|
+
# @private
|
85
|
+
def supports_block_expectations?
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
# @private
|
90
|
+
def supports_value_expectations?
|
91
|
+
false
|
92
|
+
end
|
93
|
+
|
94
|
+
# @private
|
95
|
+
def expects_call_stack_jump?
|
96
|
+
true
|
97
|
+
end
|
98
|
+
|
99
|
+
# @api private
|
100
|
+
# @return [String]
|
101
|
+
def failure_message
|
102
|
+
@eval_block ? actual_error_message : "expected #{expected_error}#{given_error}"
|
103
|
+
end
|
104
|
+
|
105
|
+
# @api private
|
106
|
+
# @return [String]
|
107
|
+
def failure_message_when_negated
|
108
|
+
"expected no #{expected_error}#{given_error}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# @api private
|
112
|
+
# @return [String]
|
113
|
+
def description
|
114
|
+
"raise #{expected_error}"
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def actual_error_message
|
120
|
+
return nil unless @actual_error
|
121
|
+
|
122
|
+
@actual_error.respond_to?(:original_message) ? @actual_error.original_message : @actual_error.message
|
123
|
+
end
|
124
|
+
|
125
|
+
def expectation_matched?
|
126
|
+
error_and_message_match? && block_matches?
|
127
|
+
end
|
128
|
+
|
129
|
+
def error_and_message_match?
|
130
|
+
@raised_expected_error && @with_expected_message
|
131
|
+
end
|
132
|
+
|
133
|
+
def block_matches?
|
134
|
+
@eval_block ? @eval_block_passed : true
|
135
|
+
end
|
136
|
+
|
137
|
+
def ready_to_eval_block?
|
138
|
+
@raised_expected_error && @with_expected_message && @block
|
54
139
|
end
|
55
140
|
|
56
141
|
def eval_block
|
@@ -64,38 +149,88 @@ module RSpec
|
|
64
149
|
end
|
65
150
|
|
66
151
|
def verify_message
|
67
|
-
|
68
|
-
|
69
|
-
true
|
70
|
-
when Regexp
|
71
|
-
@expected_message =~ @actual_error.message
|
72
|
-
else
|
73
|
-
@expected_message == @actual_error.message
|
74
|
-
end
|
152
|
+
return true if @expected_message.nil?
|
153
|
+
values_match?(@expected_message, actual_error_message.to_s)
|
75
154
|
end
|
76
155
|
|
77
|
-
def
|
78
|
-
|
156
|
+
def warn_for_negative_false_positives!
|
157
|
+
expression = if expecting_specific_exception? && @expected_message
|
158
|
+
"`expect { }.not_to raise_error(SpecificErrorClass, message)`"
|
159
|
+
elsif expecting_specific_exception?
|
160
|
+
"`expect { }.not_to raise_error(SpecificErrorClass)`"
|
161
|
+
elsif @expected_message
|
162
|
+
"`expect { }.not_to raise_error(message)`"
|
163
|
+
elsif @warn_about_nil_error
|
164
|
+
"`expect { }.not_to raise_error(nil)`"
|
165
|
+
end
|
166
|
+
|
167
|
+
return unless expression
|
168
|
+
|
169
|
+
warn_about_negative_false_positive! expression
|
79
170
|
end
|
80
171
|
|
81
|
-
def
|
82
|
-
|
172
|
+
def handle_warning(message)
|
173
|
+
RSpec::Expectations.configuration.false_positives_handler.call(message)
|
83
174
|
end
|
84
175
|
|
85
|
-
def
|
86
|
-
|
176
|
+
def warn_about_bare_error?
|
177
|
+
@warn_about_bare_error && @block.nil?
|
178
|
+
end
|
179
|
+
|
180
|
+
def warn_about_nil_error?
|
181
|
+
@warn_about_nil_error
|
182
|
+
end
|
183
|
+
|
184
|
+
def warn_about_bare_error!
|
185
|
+
handle_warning("Using the `raise_error` matcher without providing a specific " \
|
186
|
+
"error or message risks false positives, since `raise_error` " \
|
187
|
+
"will match when Ruby raises a `NoMethodError`, `NameError` or " \
|
188
|
+
"`ArgumentError`, potentially allowing the expectation to pass " \
|
189
|
+
"without even executing the method you are intending to call. " \
|
190
|
+
"#{warning}"\
|
191
|
+
"Instead consider providing a specific error class or message. " \
|
192
|
+
"This message can be suppressed by setting: " \
|
193
|
+
"`RSpec::Expectations.configuration.on_potential_false" \
|
194
|
+
"_positives = :nothing`")
|
195
|
+
end
|
196
|
+
|
197
|
+
def warn_about_nil_error!
|
198
|
+
handle_warning("Using the `raise_error` matcher with a `nil` error is probably " \
|
199
|
+
"unintentional, it risks false positives, since `raise_error` " \
|
200
|
+
"will match when Ruby raises a `NoMethodError`, `NameError` or " \
|
201
|
+
"`ArgumentError`, potentially allowing the expectation to pass " \
|
202
|
+
"without even executing the method you are intending to call. " \
|
203
|
+
"#{warning}"\
|
204
|
+
"Instead consider providing a specific error class or message. " \
|
205
|
+
"This message can be suppressed by setting: " \
|
206
|
+
"`RSpec::Expectations.configuration.on_potential_false" \
|
207
|
+
"_positives = :nothing`")
|
87
208
|
end
|
88
209
|
|
89
|
-
|
210
|
+
def warn_about_negative_false_positive!(expression)
|
211
|
+
handle_warning("Using #{expression} risks false positives, since literally " \
|
212
|
+
"any other error would cause the expectation to pass, " \
|
213
|
+
"including those raised by Ruby (e.g. `NoMethodError`, `NameError` " \
|
214
|
+
"and `ArgumentError`), meaning the code you are intending to test " \
|
215
|
+
"may not even get reached. Instead consider using " \
|
216
|
+
"`expect { }.not_to raise_error` or `expect { }.to raise_error" \
|
217
|
+
"(DifferentSpecificErrorClass)`. This message can be suppressed by " \
|
218
|
+
"setting: `RSpec::Expectations.configuration.on_potential_false" \
|
219
|
+
"_positives = :nothing`")
|
220
|
+
end
|
90
221
|
|
91
222
|
def expected_error
|
92
223
|
case @expected_message
|
93
224
|
when nil
|
94
|
-
@expected_error
|
225
|
+
if RSpec::Support.is_a_matcher?(@expected_error)
|
226
|
+
"Exception with #{description_of(@expected_error)}"
|
227
|
+
else
|
228
|
+
description_of(@expected_error)
|
229
|
+
end
|
95
230
|
when Regexp
|
96
|
-
"#{@expected_error} with message matching #{@expected_message
|
231
|
+
"#{@expected_error} with message matching #{description_of(@expected_message)}"
|
97
232
|
else
|
98
|
-
"#{@expected_error} with #{@expected_message
|
233
|
+
"#{@expected_error} with #{description_of(@expected_message)}"
|
99
234
|
end
|
100
235
|
end
|
101
236
|
|
@@ -105,11 +240,12 @@ module RSpec
|
|
105
240
|
end
|
106
241
|
|
107
242
|
def given_error
|
243
|
+
return " but was not given a block" unless Proc === @given_proc
|
108
244
|
return " but nothing was raised" unless @actual_error
|
109
245
|
|
110
246
|
backtrace = format_backtrace(@actual_error.backtrace)
|
111
247
|
[
|
112
|
-
", got #{@actual_error
|
248
|
+
", got #{description_of(@actual_error)} with backtrace:",
|
113
249
|
*backtrace
|
114
250
|
].join("\n # ")
|
115
251
|
end
|
@@ -117,7 +253,19 @@ module RSpec
|
|
117
253
|
def expecting_specific_exception?
|
118
254
|
@expected_error != Exception
|
119
255
|
end
|
256
|
+
|
257
|
+
def raise_message_already_set
|
258
|
+
raise "`expect { }.to raise_error(message).with_message(message)` is not valid. " \
|
259
|
+
'The matcher only allows the expected message to be specified once'
|
260
|
+
end
|
261
|
+
|
262
|
+
def warning
|
263
|
+
warning = "Actual error raised was #{description_of(@actual_error)}. "
|
264
|
+
warning if @actual_error
|
265
|
+
end
|
120
266
|
end
|
267
|
+
# rubocop:enable Lint/RescueException
|
268
|
+
# rubocop:enable Metrics/ClassLength
|
121
269
|
end
|
122
270
|
end
|
123
271
|
end
|