rspec-expectations 3.1.2 → 3.2.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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +45 -0
- data/README.md +17 -6
- data/lib/rspec/expectations.rb +2 -1
- data/lib/rspec/expectations/configuration.rb +1 -1
- data/lib/rspec/expectations/fail_with.rb +1 -2
- data/lib/rspec/expectations/handler.rb +13 -10
- data/lib/rspec/expectations/minitest_integration.rb +1 -0
- data/lib/rspec/expectations/syntax.rb +1 -1
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +37 -49
- data/lib/rspec/matchers/built_in.rb +2 -2
- data/lib/rspec/matchers/built_in/be.rb +6 -10
- data/lib/rspec/matchers/built_in/compound.rb +38 -3
- data/lib/rspec/matchers/built_in/have_attributes.rb +34 -5
- data/lib/rspec/matchers/built_in/include.rb +3 -3
- data/lib/rspec/matchers/built_in/output.rb +41 -0
- data/lib/rspec/matchers/built_in/{start_and_end_with.rb → start_or_end_with.rb} +17 -7
- data/lib/rspec/matchers/built_in/yield.rb +8 -12
- data/lib/rspec/matchers/dsl.rb +56 -7
- data/lib/rspec/matchers/expecteds_for_multiple_diffs.rb +79 -0
- data/lib/rspec/matchers/matcher_protocol.rb +66 -66
- metadata +41 -28
- metadata.gz.sig +0 -0
@@ -24,7 +24,7 @@ module RSpec
|
|
24
24
|
autoload :Compound, 'rspec/matchers/built_in/compound'
|
25
25
|
autoload :ContainExactly, 'rspec/matchers/built_in/contain_exactly'
|
26
26
|
autoload :Cover, 'rspec/matchers/built_in/cover'
|
27
|
-
autoload :EndWith, 'rspec/matchers/built_in/
|
27
|
+
autoload :EndWith, 'rspec/matchers/built_in/start_or_end_with'
|
28
28
|
autoload :Eq, 'rspec/matchers/built_in/eq'
|
29
29
|
autoload :Eql, 'rspec/matchers/built_in/eql'
|
30
30
|
autoload :Equal, 'rspec/matchers/built_in/equal'
|
@@ -41,7 +41,7 @@ module RSpec
|
|
41
41
|
autoload :RaiseError, 'rspec/matchers/built_in/raise_error'
|
42
42
|
autoload :RespondTo, 'rspec/matchers/built_in/respond_to'
|
43
43
|
autoload :Satisfy, 'rspec/matchers/built_in/satisfy'
|
44
|
-
autoload :StartWith, 'rspec/matchers/built_in/
|
44
|
+
autoload :StartWith, 'rspec/matchers/built_in/start_or_end_with'
|
45
45
|
autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol'
|
46
46
|
autoload :YieldControl, 'rspec/matchers/built_in/yield'
|
47
47
|
autoload :YieldSuccessiveArgs, 'rspec/matchers/built_in/yield'
|
@@ -215,7 +215,7 @@ module RSpec
|
|
215
215
|
private
|
216
216
|
|
217
217
|
def predicate_accessible?
|
218
|
-
|
218
|
+
actual.respond_to?(predicate) || actual.respond_to?(present_tense_predicate)
|
219
219
|
end
|
220
220
|
|
221
221
|
# support 1.8.7, evaluate once at load time for performance
|
@@ -229,10 +229,6 @@ module RSpec
|
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
232
|
-
def predicate_exists?
|
233
|
-
actual.respond_to?(predicate) || actual.respond_to?(present_tense_predicate)
|
234
|
-
end
|
235
|
-
|
236
232
|
def predicate_matches?
|
237
233
|
method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate
|
238
234
|
@predicate_matches = actual.__send__(method_name, *@args, &@block)
|
@@ -265,11 +261,11 @@ module RSpec
|
|
265
261
|
end
|
266
262
|
|
267
263
|
def validity_message
|
268
|
-
if
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
264
|
+
return nil if predicate_accessible?
|
265
|
+
|
266
|
+
msg = "expected #{@actual} to respond to `#{predicate}`"
|
267
|
+
msg << " but `#{predicate}` is a private method" if private_predicate?
|
268
|
+
msg
|
273
269
|
end
|
274
270
|
end
|
275
271
|
end
|
@@ -3,9 +3,10 @@ module RSpec
|
|
3
3
|
module BuiltIn
|
4
4
|
# @api private
|
5
5
|
# Base class for `and` and `or` compound matchers.
|
6
|
+
# rubocop:disable ClassLength
|
6
7
|
class Compound < BaseMatcher
|
7
8
|
# @private
|
8
|
-
attr_reader :matcher_1, :matcher_2
|
9
|
+
attr_reader :matcher_1, :matcher_2, :evaluator
|
9
10
|
|
10
11
|
def initialize(matcher_1, matcher_2)
|
11
12
|
@matcher_1 = matcher_1
|
@@ -36,6 +37,28 @@ module RSpec
|
|
36
37
|
NestedEvaluator.matcher_expects_call_stack_jump?(matcher_2)
|
37
38
|
end
|
38
39
|
|
40
|
+
# @api private
|
41
|
+
# @return [Boolean]
|
42
|
+
def diffable?
|
43
|
+
matcher_is_diffable?(matcher_1) || matcher_is_diffable?(matcher_2)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
# @return [RSpec::Matchers::ExpectedsForMultipleDiffs]
|
48
|
+
def expected
|
49
|
+
return nil unless evaluator
|
50
|
+
::RSpec::Matchers::ExpectedsForMultipleDiffs.for_many_matchers(diffable_matcher_list)
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def diffable_matcher_list
|
56
|
+
list = []
|
57
|
+
list.concat(diffable_matcher_list_for(matcher_1)) unless matcher_1_matches?
|
58
|
+
list.concat(diffable_matcher_list_for(matcher_2)) unless matcher_2_matches?
|
59
|
+
list
|
60
|
+
end
|
61
|
+
|
39
62
|
private
|
40
63
|
|
41
64
|
def initialize_copy(other)
|
@@ -88,11 +111,11 @@ module RSpec
|
|
88
111
|
end
|
89
112
|
|
90
113
|
def matcher_1_matches?
|
91
|
-
|
114
|
+
evaluator.matcher_matches?(matcher_1)
|
92
115
|
end
|
93
116
|
|
94
117
|
def matcher_2_matches?
|
95
|
-
|
118
|
+
evaluator.matcher_matches?(matcher_2)
|
96
119
|
end
|
97
120
|
|
98
121
|
def matcher_supports_block_expectations?(matcher)
|
@@ -101,6 +124,18 @@ module RSpec
|
|
101
124
|
false
|
102
125
|
end
|
103
126
|
|
127
|
+
def matcher_is_diffable?(matcher)
|
128
|
+
matcher.diffable?
|
129
|
+
rescue NoMethodError
|
130
|
+
false
|
131
|
+
end
|
132
|
+
|
133
|
+
def diffable_matcher_list_for(matcher)
|
134
|
+
return [] unless matcher_is_diffable?(matcher)
|
135
|
+
return matcher.diffable_matcher_list if Compound === matcher
|
136
|
+
[matcher]
|
137
|
+
end
|
138
|
+
|
104
139
|
# For value expectations, we can evaluate the matchers sequentially.
|
105
140
|
class SequentialEvaluator
|
106
141
|
def initialize(actual, *)
|
@@ -10,13 +10,21 @@ module RSpec
|
|
10
10
|
|
11
11
|
def initialize(expected)
|
12
12
|
@expected = expected
|
13
|
+
@values = {}
|
13
14
|
@respond_to_failed = false
|
15
|
+
@negated = false
|
16
|
+
end
|
17
|
+
|
18
|
+
# @private
|
19
|
+
def actual
|
20
|
+
@values
|
14
21
|
end
|
15
22
|
|
16
23
|
# @api private
|
17
24
|
# @return [Boolean]
|
18
25
|
def matches?(actual)
|
19
26
|
@actual = actual
|
27
|
+
@negated = false
|
20
28
|
return false unless respond_to_attributes?
|
21
29
|
perform_match(:all?)
|
22
30
|
end
|
@@ -25,6 +33,7 @@ module RSpec
|
|
25
33
|
# @return [Boolean]
|
26
34
|
def does_not_match?(actual)
|
27
35
|
@actual = actual
|
36
|
+
@negated = true
|
28
37
|
return false unless respond_to_attributes?
|
29
38
|
perform_match(:none?)
|
30
39
|
end
|
@@ -36,33 +45,49 @@ module RSpec
|
|
36
45
|
improve_hash_formatting "have attributes #{described_items.inspect}"
|
37
46
|
end
|
38
47
|
|
48
|
+
# @api private
|
49
|
+
# @return [Boolean]
|
50
|
+
def diffable?
|
51
|
+
!@respond_to_failed && !@negated
|
52
|
+
end
|
53
|
+
|
39
54
|
# @api private
|
40
55
|
# @return [String]
|
41
56
|
def failure_message
|
42
|
-
respond_to_failure_message_or
|
57
|
+
respond_to_failure_message_or do
|
58
|
+
"expected #{@actual.inspect} to #{description} but had attributes #{ formatted_values }"
|
59
|
+
end
|
43
60
|
end
|
44
61
|
|
45
62
|
# @api private
|
46
63
|
# @return [String]
|
47
64
|
def failure_message_when_negated
|
48
|
-
respond_to_failure_message_or {
|
65
|
+
respond_to_failure_message_or { "expected #{@actual.inspect} not to #{description}" }
|
49
66
|
end
|
50
67
|
|
51
68
|
private
|
52
69
|
|
70
|
+
def cache_all_values
|
71
|
+
@values = {}
|
72
|
+
expected.each do |attribute_key, _attribute_value|
|
73
|
+
actual_value = @actual.__send__(attribute_key)
|
74
|
+
@values[attribute_key] = actual_value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
53
78
|
def perform_match(predicate)
|
79
|
+
cache_all_values
|
54
80
|
expected.__send__(predicate) do |attribute_key, attribute_value|
|
55
81
|
actual_has_attribute?(attribute_key, attribute_value)
|
56
82
|
end
|
57
83
|
end
|
58
84
|
|
59
85
|
def actual_has_attribute?(attribute_key, attribute_value)
|
60
|
-
|
61
|
-
values_match?(attribute_value, actual_value)
|
86
|
+
values_match?(attribute_value, @values.fetch(attribute_key))
|
62
87
|
end
|
63
88
|
|
64
89
|
def respond_to_attributes?
|
65
|
-
matches = respond_to_matcher.matches?(actual)
|
90
|
+
matches = respond_to_matcher.matches?(@actual)
|
66
91
|
@respond_to_failed = !matches
|
67
92
|
matches
|
68
93
|
end
|
@@ -78,6 +103,10 @@ module RSpec
|
|
78
103
|
improve_hash_formatting(yield)
|
79
104
|
end
|
80
105
|
end
|
106
|
+
|
107
|
+
def formatted_values
|
108
|
+
improve_hash_formatting(@values.inspect)
|
109
|
+
end
|
81
110
|
end
|
82
111
|
end
|
83
112
|
end
|
@@ -33,13 +33,13 @@ module RSpec
|
|
33
33
|
# @api private
|
34
34
|
# @return [String]
|
35
35
|
def failure_message
|
36
|
-
improve_hash_formatting(super) +
|
36
|
+
improve_hash_formatting(super) + invalid_object_message
|
37
37
|
end
|
38
38
|
|
39
39
|
# @api private
|
40
40
|
# @return [String]
|
41
41
|
def failure_message_when_negated
|
42
|
-
improve_hash_formatting(super) +
|
42
|
+
improve_hash_formatting(super) + invalid_object_message
|
43
43
|
end
|
44
44
|
|
45
45
|
# @api private
|
@@ -50,7 +50,7 @@ module RSpec
|
|
50
50
|
|
51
51
|
private
|
52
52
|
|
53
|
-
def
|
53
|
+
def invalid_object_message
|
54
54
|
return '' if actual.respond_to?(:include?)
|
55
55
|
", but it does not respond to `include?`"
|
56
56
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'stringio'
|
2
|
+
require 'tempfile'
|
2
3
|
|
3
4
|
module RSpec
|
4
5
|
module Matchers
|
@@ -27,6 +28,7 @@ module RSpec
|
|
27
28
|
|
28
29
|
# @api public
|
29
30
|
# Tells the matcher to match against stdout.
|
31
|
+
# Works only when the main Ruby process prints to stdout
|
30
32
|
def to_stdout
|
31
33
|
@stream_capturer = CaptureStdout
|
32
34
|
self
|
@@ -34,11 +36,30 @@ module RSpec
|
|
34
36
|
|
35
37
|
# @api public
|
36
38
|
# Tells the matcher to match against stderr.
|
39
|
+
# Works only when the main Ruby process prints to stderr
|
37
40
|
def to_stderr
|
38
41
|
@stream_capturer = CaptureStderr
|
39
42
|
self
|
40
43
|
end
|
41
44
|
|
45
|
+
# @api public
|
46
|
+
# Tells the matcher to match against stdout.
|
47
|
+
# Works when subprocesses print to stdout as well.
|
48
|
+
# This is significantly (~30x) slower than `to_stdout`
|
49
|
+
def to_stdout_from_any_process
|
50
|
+
@stream_capturer = CaptureStreamToTempfile.new("stdout", $stdout)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# @api public
|
55
|
+
# Tells the matcher to match against stderr.
|
56
|
+
# Works when subprocesses print to stderr as well.
|
57
|
+
# This is significantly (~30x) slower than `to_stderr`
|
58
|
+
def to_stderr_from_any_process
|
59
|
+
@stream_capturer = CaptureStreamToTempfile.new("stderr", $stderr)
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
42
63
|
# @api private
|
43
64
|
# @return [String]
|
44
65
|
def failure_message
|
@@ -147,6 +168,26 @@ module RSpec
|
|
147
168
|
$stderr = original_stream
|
148
169
|
end
|
149
170
|
end
|
171
|
+
|
172
|
+
# @private
|
173
|
+
class CaptureStreamToTempfile < Struct.new(:name, :stream)
|
174
|
+
def capture(block)
|
175
|
+
original_stream = stream.clone
|
176
|
+
captured_stream = Tempfile.new(name)
|
177
|
+
|
178
|
+
begin
|
179
|
+
captured_stream.sync = true
|
180
|
+
stream.reopen(captured_stream)
|
181
|
+
block.call
|
182
|
+
captured_stream.rewind
|
183
|
+
captured_stream.read
|
184
|
+
ensure
|
185
|
+
stream.reopen(original_stream)
|
186
|
+
captured_stream.close
|
187
|
+
captured_stream.unlink
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
150
191
|
end
|
151
192
|
end
|
152
193
|
end
|
@@ -4,7 +4,7 @@ module RSpec
|
|
4
4
|
# @api private
|
5
5
|
# Base class for the `end_with` and `start_with` matchers.
|
6
6
|
# Not intended to be instantiated directly.
|
7
|
-
class
|
7
|
+
class StartOrEndWith < BaseMatcher
|
8
8
|
def initialize(*expected)
|
9
9
|
@actual_does_not_have_ordered_elements = false
|
10
10
|
@expected = expected.length == 1 ? expected.first : expected
|
@@ -31,11 +31,11 @@ module RSpec
|
|
31
31
|
|
32
32
|
private
|
33
33
|
|
34
|
-
def match(
|
34
|
+
def match(_expected, actual)
|
35
35
|
return false unless actual.respond_to?(:[])
|
36
36
|
|
37
37
|
begin
|
38
|
-
return
|
38
|
+
return true if subsets_comparable? && subset_matches?
|
39
39
|
element_matches?
|
40
40
|
rescue ArgumentError
|
41
41
|
@actual_does_not_have_ordered_elements = true
|
@@ -43,15 +43,25 @@ module RSpec
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
47
|
-
|
46
|
+
def subsets_comparable?
|
47
|
+
# Structs support the Enumerable interface but don't really have
|
48
|
+
# the semantics of a subset of a larger set...
|
49
|
+
return false if Struct === expected
|
50
|
+
|
51
|
+
expected.respond_to?(:length)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
55
|
+
# For RSpec 3.1, the base class was named `StartAndEndWith`. For SemVer reasons,
|
56
|
+
# we still provide this constant until 4.0.
|
57
|
+
# @deprecated Use StartOrEndWith instead.
|
58
|
+
# @private
|
59
|
+
StartAndEndWith = StartOrEndWith
|
60
|
+
|
51
61
|
# @api private
|
52
62
|
# Provides the implementation for `start_with`.
|
53
63
|
# Not intended to be instantiated directly.
|
54
|
-
class StartWith <
|
64
|
+
class StartWith < StartOrEndWith
|
55
65
|
private
|
56
66
|
|
57
67
|
def subset_matches?
|
@@ -66,7 +76,7 @@ module RSpec
|
|
66
76
|
# @api private
|
67
77
|
# Provides the implementation for `end_with`.
|
68
78
|
# Not intended to be instantiated directly.
|
69
|
-
class EndWith <
|
79
|
+
class EndWith < StartOrEndWith
|
70
80
|
private
|
71
81
|
|
72
82
|
def subset_matches?
|
@@ -94,8 +94,7 @@ module RSpec
|
|
94
94
|
# Not intended to be instantiated directly.
|
95
95
|
class YieldControl < BaseMatcher
|
96
96
|
def initialize
|
97
|
-
|
98
|
-
@expected_yields_count = nil
|
97
|
+
at_least(:once)
|
99
98
|
end
|
100
99
|
|
101
100
|
# @api public
|
@@ -151,11 +150,7 @@ module RSpec
|
|
151
150
|
@probe = YieldProbe.probe(block)
|
152
151
|
return false unless @probe.has_block?
|
153
152
|
|
154
|
-
|
155
|
-
@probe.num_yields.__send__(@expectation_type, @expected_yields_count)
|
156
|
-
else
|
157
|
-
@probe.yielded_once?(:yield_control)
|
158
|
-
end
|
153
|
+
@probe.num_yields.__send__(@expectation_type, @expected_yields_count)
|
159
154
|
end
|
160
155
|
|
161
156
|
# @private
|
@@ -195,10 +190,11 @@ module RSpec
|
|
195
190
|
def failure_reason
|
196
191
|
return " but was not a block" unless @probe.has_block?
|
197
192
|
return '' unless @expected_yields_count
|
198
|
-
" #{
|
193
|
+
" #{human_readable_expectation_type}#{human_readable_count(@expected_yields_count)}" \
|
194
|
+
" but yielded #{human_readable_count(@probe.num_yields)}"
|
199
195
|
end
|
200
196
|
|
201
|
-
def
|
197
|
+
def human_readable_expectation_type
|
202
198
|
case @expectation_type
|
203
199
|
when :<= then 'at most '
|
204
200
|
when :>= then 'at least '
|
@@ -206,11 +202,11 @@ module RSpec
|
|
206
202
|
end
|
207
203
|
end
|
208
204
|
|
209
|
-
def human_readable_count
|
210
|
-
case
|
205
|
+
def human_readable_count(count)
|
206
|
+
case count
|
211
207
|
when 1 then "once"
|
212
208
|
when 2 then "twice"
|
213
|
-
else "#{
|
209
|
+
else "#{count} times"
|
214
210
|
end
|
215
211
|
end
|
216
212
|
end
|
data/lib/rspec/matchers/dsl.rb
CHANGED
@@ -5,12 +5,30 @@ module RSpec
|
|
5
5
|
# Defines a custom matcher.
|
6
6
|
# @see RSpec::Matchers
|
7
7
|
def define(name, &declarations)
|
8
|
-
|
9
|
-
|
8
|
+
warn_about_block_args(name, declarations)
|
9
|
+
define_method name do |*expected, &block_arg|
|
10
|
+
RSpec::Matchers::DSL::Matcher.new(name, declarations, self, *expected, &block_arg)
|
10
11
|
end
|
11
12
|
end
|
12
13
|
alias_method :matcher, :define
|
13
14
|
|
15
|
+
private
|
16
|
+
|
17
|
+
if Proc.method_defined?(:parameters)
|
18
|
+
def warn_about_block_args(name, declarations)
|
19
|
+
declarations.parameters.each do |type, arg_name|
|
20
|
+
next unless type == :block
|
21
|
+
RSpec.warning("Your `#{name}` custom matcher receives a block argument (`#{arg_name}`), " \
|
22
|
+
"but due to limitations in ruby, RSpec cannot provide the block. Instead, " \
|
23
|
+
"use the `block_arg` method to access the block")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
else
|
27
|
+
def warn_about_block_args(*)
|
28
|
+
# There's no way to detect block params on 1.8 since the method reflection APIs don't expose it
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
14
32
|
RSpec.configure { |c| c.extend self } if RSpec.respond_to?(:configure)
|
15
33
|
|
16
34
|
# Contains the methods that are available from within the
|
@@ -165,6 +183,12 @@ module RSpec
|
|
165
183
|
# hash been enabled, the chained method name and args will be added to the
|
166
184
|
# default description and failure message.
|
167
185
|
#
|
186
|
+
# In the common case where you just want the chained method to store some
|
187
|
+
# value(s) for later use (e.g. in `match`), you can provide one or more
|
188
|
+
# attribute names instead of a block; the chained method will store its
|
189
|
+
# arguments in instance variables with those names, and the values will
|
190
|
+
# be exposed via getters.
|
191
|
+
#
|
168
192
|
# @example
|
169
193
|
#
|
170
194
|
# RSpec::Matchers.define :have_errors_on do |key|
|
@@ -178,19 +202,40 @@ module RSpec
|
|
178
202
|
# end
|
179
203
|
#
|
180
204
|
# expect(minor).to have_errors_on(:age).with("Not old enough to participate")
|
181
|
-
def chain(
|
182
|
-
|
205
|
+
def chain(method_name, *attr_names, &definition)
|
206
|
+
unless block_given? ^ attr_names.any?
|
207
|
+
raise ArgumentError, "You must pass either a block or some attribute names (but not both) to `chain`."
|
208
|
+
end
|
209
|
+
|
210
|
+
definition = assign_attributes(attr_names) if attr_names.any?
|
211
|
+
|
212
|
+
define_user_override(method_name, definition) do |*args, &block|
|
183
213
|
super(*args, &block)
|
184
|
-
@chained_method_clauses.push([
|
214
|
+
@chained_method_clauses.push([method_name, args])
|
185
215
|
self
|
186
216
|
end
|
187
217
|
end
|
188
218
|
|
219
|
+
def assign_attributes(attr_names)
|
220
|
+
attr_reader(*attr_names)
|
221
|
+
private(*attr_names)
|
222
|
+
|
223
|
+
lambda do |*attr_values|
|
224
|
+
attr_names.zip(attr_values) do |attr_name, attr_value|
|
225
|
+
instance_variable_set(:"@#{attr_name}", attr_value)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# assign_attributes isn't defined in the private section below because
|
231
|
+
# that makes MRI 1.9.2 emit a warning about private attributes.
|
232
|
+
private :assign_attributes
|
233
|
+
|
189
234
|
private
|
190
235
|
|
191
236
|
# Does the following:
|
192
237
|
#
|
193
|
-
# - Defines the named method
|
238
|
+
# - Defines the named method using a user-provided block
|
194
239
|
# in @user_method_defs, which is included as an ancestor
|
195
240
|
# in the singleton class in which we eval the `define` block.
|
196
241
|
# - Defines an overriden definition for the same method
|
@@ -309,13 +354,17 @@ module RSpec
|
|
309
354
|
# Could be useful to extract details for a failure message.
|
310
355
|
attr_reader :rescued_exception
|
311
356
|
|
357
|
+
# The block parameter used in the expectation
|
358
|
+
attr_reader :block_arg
|
359
|
+
|
312
360
|
# @api private
|
313
|
-
def initialize(name, declarations, matcher_execution_context, *expected)
|
361
|
+
def initialize(name, declarations, matcher_execution_context, *expected, &block_arg)
|
314
362
|
@name = name
|
315
363
|
@actual = nil
|
316
364
|
@expected_as_array = expected
|
317
365
|
@matcher_execution_context = matcher_execution_context
|
318
366
|
@chained_method_clauses = []
|
367
|
+
@block_arg = block_arg
|
319
368
|
|
320
369
|
class << self
|
321
370
|
# See `Macros#define_user_override` above, for an explanation.
|