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.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +1 -1
  5. data/Changelog.md +976 -25
  6. data/{License.txt → LICENSE.md} +5 -3
  7. data/README.md +162 -26
  8. data/lib/rspec/expectations/block_snippet_extractor.rb +253 -0
  9. data/lib/rspec/expectations/configuration.rb +230 -0
  10. data/lib/rspec/expectations/expectation_target.rb +127 -51
  11. data/lib/rspec/expectations/fail_with.rb +17 -57
  12. data/lib/rspec/expectations/failure_aggregator.rb +229 -0
  13. data/lib/rspec/expectations/handler.rb +146 -32
  14. data/lib/rspec/expectations/minitest_integration.rb +58 -0
  15. data/lib/rspec/expectations/syntax.rb +68 -100
  16. data/lib/rspec/expectations/version.rb +1 -1
  17. data/lib/rspec/expectations.rb +58 -23
  18. data/lib/rspec/matchers/aliased_matcher.rb +116 -0
  19. data/lib/rspec/matchers/built_in/all.rb +86 -0
  20. data/lib/rspec/matchers/built_in/base_matcher.rb +191 -20
  21. data/lib/rspec/matchers/built_in/be.rb +114 -114
  22. data/lib/rspec/matchers/built_in/be_between.rb +77 -0
  23. data/lib/rspec/matchers/built_in/be_instance_of.rb +15 -4
  24. data/lib/rspec/matchers/built_in/be_kind_of.rb +10 -1
  25. data/lib/rspec/matchers/built_in/be_within.rb +35 -18
  26. data/lib/rspec/matchers/built_in/change.rb +389 -80
  27. data/lib/rspec/matchers/built_in/compound.rb +290 -0
  28. data/lib/rspec/matchers/built_in/contain_exactly.rb +310 -0
  29. data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
  30. data/lib/rspec/matchers/built_in/cover.rb +3 -0
  31. data/lib/rspec/matchers/built_in/eq.rb +30 -8
  32. data/lib/rspec/matchers/built_in/eql.rb +23 -8
  33. data/lib/rspec/matchers/built_in/equal.rb +55 -22
  34. data/lib/rspec/matchers/built_in/exist.rb +74 -10
  35. data/lib/rspec/matchers/built_in/has.rb +141 -22
  36. data/lib/rspec/matchers/built_in/have_attributes.rb +114 -0
  37. data/lib/rspec/matchers/built_in/include.rb +184 -32
  38. data/lib/rspec/matchers/built_in/match.rb +95 -1
  39. data/lib/rspec/matchers/built_in/operators.rb +128 -0
  40. data/lib/rspec/matchers/built_in/output.rb +207 -0
  41. data/lib/rspec/matchers/built_in/raise_error.rb +192 -44
  42. data/lib/rspec/matchers/built_in/respond_to.rb +154 -28
  43. data/lib/rspec/matchers/built_in/satisfy.rb +39 -9
  44. data/lib/rspec/matchers/built_in/start_or_end_with.rb +94 -0
  45. data/lib/rspec/matchers/built_in/throw_symbol.rb +58 -14
  46. data/lib/rspec/matchers/built_in/yield.rb +240 -161
  47. data/lib/rspec/matchers/built_in.rb +47 -33
  48. data/lib/rspec/matchers/composable.rb +171 -0
  49. data/lib/rspec/matchers/dsl.rb +531 -10
  50. data/lib/rspec/matchers/english_phrasing.rb +58 -0
  51. data/lib/rspec/matchers/fail_matchers.rb +42 -0
  52. data/lib/rspec/matchers/generated_descriptions.rb +14 -8
  53. data/lib/rspec/matchers/matcher_delegator.rb +61 -0
  54. data/lib/rspec/matchers/matcher_protocol.rb +105 -0
  55. data/lib/rspec/matchers/multi_matcher_diff.rb +82 -0
  56. data/lib/rspec/matchers.rb +520 -173
  57. data.tar.gz.sig +0 -0
  58. metadata +141 -242
  59. metadata.gz.sig +2 -0
  60. data/features/README.md +0 -48
  61. data/features/Upgrade.md +0 -53
  62. data/features/built_in_matchers/README.md +0 -90
  63. data/features/built_in_matchers/be.feature +0 -175
  64. data/features/built_in_matchers/be_within.feature +0 -48
  65. data/features/built_in_matchers/cover.feature +0 -47
  66. data/features/built_in_matchers/end_with.feature +0 -48
  67. data/features/built_in_matchers/equality.feature +0 -139
  68. data/features/built_in_matchers/exist.feature +0 -45
  69. data/features/built_in_matchers/expect_change.feature +0 -59
  70. data/features/built_in_matchers/expect_error.feature +0 -144
  71. data/features/built_in_matchers/have.feature +0 -109
  72. data/features/built_in_matchers/include.feature +0 -174
  73. data/features/built_in_matchers/match.feature +0 -52
  74. data/features/built_in_matchers/operators.feature +0 -227
  75. data/features/built_in_matchers/predicates.feature +0 -137
  76. data/features/built_in_matchers/respond_to.feature +0 -84
  77. data/features/built_in_matchers/satisfy.feature +0 -33
  78. data/features/built_in_matchers/start_with.feature +0 -48
  79. data/features/built_in_matchers/throw_symbol.feature +0 -91
  80. data/features/built_in_matchers/types.feature +0 -116
  81. data/features/built_in_matchers/yield.feature +0 -161
  82. data/features/custom_matchers/access_running_example.feature +0 -53
  83. data/features/custom_matchers/define_diffable_matcher.feature +0 -27
  84. data/features/custom_matchers/define_matcher.feature +0 -368
  85. data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
  86. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
  87. data/features/customized_message.feature +0 -22
  88. data/features/diffing.feature +0 -85
  89. data/features/implicit_docstrings.feature +0 -52
  90. data/features/step_definitions/additional_cli_steps.rb +0 -22
  91. data/features/support/env.rb +0 -14
  92. data/features/syntax_configuration.feature +0 -71
  93. data/features/test_frameworks/test_unit.feature +0 -44
  94. data/lib/rspec/expectations/deprecation.rb +0 -17
  95. data/lib/rspec/expectations/differ.rb +0 -133
  96. data/lib/rspec/expectations/errors.rb +0 -9
  97. data/lib/rspec/expectations/extensions/array.rb +0 -9
  98. data/lib/rspec/expectations/extensions/object.rb +0 -29
  99. data/lib/rspec/expectations/extensions.rb +0 -2
  100. data/lib/rspec/matchers/be_close.rb +0 -9
  101. data/lib/rspec/matchers/built_in/have.rb +0 -124
  102. data/lib/rspec/matchers/built_in/match_array.rb +0 -51
  103. data/lib/rspec/matchers/built_in/start_and_end_with.rb +0 -48
  104. data/lib/rspec/matchers/compatibility.rb +0 -14
  105. data/lib/rspec/matchers/configuration.rb +0 -108
  106. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  107. data/lib/rspec/matchers/matcher.rb +0 -300
  108. data/lib/rspec/matchers/method_missing.rb +0 -12
  109. data/lib/rspec/matchers/operator_matcher.rb +0 -109
  110. data/lib/rspec/matchers/pretty.rb +0 -70
  111. data/lib/rspec/matchers/test_unit_integration.rb +0 -11
  112. data/lib/rspec-expectations.rb +0 -1
  113. data/spec/rspec/expectations/differ_spec.rb +0 -192
  114. data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
  115. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  116. data/spec/rspec/expectations/fail_with_spec.rb +0 -114
  117. data/spec/rspec/expectations/handler_spec.rb +0 -227
  118. data/spec/rspec/expectations/syntax_spec.rb +0 -139
  119. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  120. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  121. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  122. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  123. data/spec/rspec/matchers/be_spec.rb +0 -516
  124. data/spec/rspec/matchers/be_within_spec.rb +0 -137
  125. data/spec/rspec/matchers/change_spec.rb +0 -553
  126. data/spec/rspec/matchers/configuration_spec.rb +0 -206
  127. data/spec/rspec/matchers/cover_spec.rb +0 -69
  128. data/spec/rspec/matchers/description_generation_spec.rb +0 -190
  129. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  130. data/spec/rspec/matchers/eq_spec.rb +0 -60
  131. data/spec/rspec/matchers/eql_spec.rb +0 -41
  132. data/spec/rspec/matchers/equal_spec.rb +0 -78
  133. data/spec/rspec/matchers/exist_spec.rb +0 -124
  134. data/spec/rspec/matchers/has_spec.rb +0 -122
  135. data/spec/rspec/matchers/have_spec.rb +0 -455
  136. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  137. data/spec/rspec/matchers/include_spec.rb +0 -531
  138. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  139. data/spec/rspec/matchers/match_spec.rb +0 -61
  140. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  141. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  142. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  143. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  144. data/spec/rspec/matchers/raise_error_spec.rb +0 -485
  145. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  146. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  147. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  148. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  149. data/spec/rspec/matchers/yield_spec.rb +0 -514
  150. data/spec/spec_helper.rb +0 -54
  151. data/spec/support/classes.rb +0 -56
  152. data/spec/support/in_sub_process.rb +0 -38
  153. data/spec/support/matchers.rb +0 -22
  154. data/spec/support/ruby_version.rb +0 -10
  155. data/spec/support/shared_examples.rb +0 -13
@@ -1,29 +1,52 @@
1
+ require 'rspec/matchers/built_in/count_expectation'
2
+
3
+ RSpec::Support.require_rspec_support 'method_signature_verifier'
4
+
1
5
  module RSpec
2
6
  module Matchers
3
7
  module BuiltIn
8
+ # @private
9
+ # Object that is yielded to `expect` when one of the
10
+ # yield matchers is used. Provides information about
11
+ # the yield behavior of the object-under-test.
4
12
  class YieldProbe
5
- def self.probe(block)
6
- probe = new
7
- assert_valid_expect_block!(block)
8
- block.call(probe)
9
- probe.assert_used!
10
- probe
13
+ def self.probe(block, &callback)
14
+ probe = new(block, &callback)
15
+ return probe unless probe.has_block?
16
+ probe.probe
11
17
  end
12
18
 
13
19
  attr_accessor :num_yields, :yielded_args
14
20
 
15
- def initialize
21
+ def initialize(block, &callback)
22
+ @block = block
23
+ @callback = callback || Proc.new {}
16
24
  @used = false
17
- self.num_yields, self.yielded_args = 0, []
25
+ self.num_yields = 0
26
+ self.yielded_args = []
27
+ end
28
+
29
+ def has_block?
30
+ Proc === @block
31
+ end
32
+
33
+ def probe
34
+ assert_valid_expect_block!
35
+ @block.call(self)
36
+ assert_used!
37
+ self
18
38
  end
19
39
 
20
40
  def to_proc
21
41
  @used = true
22
42
 
23
43
  probe = self
44
+ callback = @callback
24
45
  Proc.new do |*args|
25
46
  probe.num_yields += 1
26
47
  probe.yielded_args << args
48
+ callback.call(*args)
49
+ nil # to indicate the block does not return a meaningful value
27
50
  end
28
51
  end
29
52
 
@@ -36,261 +59,317 @@ module RSpec
36
59
  when 1 then true
37
60
  when 0 then false
38
61
  else
39
- raise "The #{matcher_name} matcher is not designed to be used with a " +
40
- "method that yields multiple times. Use the yield_successive_args " +
41
- "matcher for that case."
42
- end
43
- end
44
-
45
- def successive_yield_args
46
- yielded_args.map do |arg_array|
47
- arg_array.size == 1 ? arg_array.first : arg_array
62
+ raise "The #{matcher_name} matcher is not designed to be used with a " \
63
+ 'method that yields multiple times. Use the yield_successive_args ' \
64
+ 'matcher for that case.'
48
65
  end
49
66
  end
50
67
 
51
68
  def assert_used!
52
69
  return if @used
53
- raise "You must pass the argument yielded to your expect block on " +
54
- "to the method-under-test as a block. It acts as a probe that " +
55
- "allows the matcher to detect whether or not the method-under-test " +
56
- "yields, and, if so, how many times, and what the yielded arguments " +
57
- "are."
58
- end
59
-
60
- def self.assert_valid_expect_block!(block)
61
- return if block.arity == 1
62
- raise "Your expect block must accept an argument to be used with this " +
63
- "matcher. Pass the argument as a block on to the method you are testing."
70
+ raise 'You must pass the argument yielded to your expect block on ' \
71
+ 'to the method-under-test as a block. It acts as a probe that ' \
72
+ 'allows the matcher to detect whether or not the method-under-test ' \
73
+ 'yields, and, if so, how many times, and what the yielded arguments ' \
74
+ 'are.'
75
+ end
76
+
77
+ if RUBY_VERSION.to_f > 1.8
78
+ def assert_valid_expect_block!
79
+ block_signature = RSpec::Support::BlockSignature.new(@block)
80
+ return if RSpec::Support::StrictSignatureVerifier.new(block_signature, [self]).valid?
81
+ raise 'Your expect block must accept an argument to be used with this ' \
82
+ 'matcher. Pass the argument as a block on to the method you are testing.'
83
+ end
84
+ else
85
+ # :nocov:
86
+ # On 1.8.7, `lambda { }.arity` and `lambda { |*a| }.arity` both return -1,
87
+ # so we can't distinguish between accepting no args and an arg splat.
88
+ # It's OK to skip, this, though; it just provides a nice error message
89
+ # when the user forgets to accept an arg in their block. They'll still get
90
+ # the `assert_used!` error message from above, which is sufficient.
91
+ def assert_valid_expect_block!
92
+ # nothing to do
93
+ end
94
+ # :nocov:
64
95
  end
65
96
  end
66
97
 
98
+ # @api private
99
+ # Provides the implementation for `yield_control`.
100
+ # Not intended to be instantiated directly.
67
101
  class YieldControl < BaseMatcher
68
- def initialize
69
- @expectation_type = nil
70
- @expected_yields_count = nil
71
- end
72
-
102
+ include CountExpectation
103
+ # @private
73
104
  def matches?(block)
74
- probe = YieldProbe.probe(block)
75
-
76
- if @expectation_type
77
- probe.num_yields.send(@expectation_type, @expected_yields_count)
78
- else
79
- probe.yielded_once?(:yield_control)
80
- end
105
+ @probe = YieldProbe.probe(block)
106
+ return false unless @probe.has_block?
107
+ expected_count_matches?(@probe.num_yields)
81
108
  end
82
109
 
83
- def once
84
- exactly(1)
85
- self
110
+ # @private
111
+ def does_not_match?(block)
112
+ !matches?(block) && @probe.has_block?
86
113
  end
87
114
 
88
- def twice
89
- exactly(2)
90
- self
115
+ # @api private
116
+ # @return [String]
117
+ def failure_message
118
+ 'expected given block to yield control' + failure_reason
91
119
  end
92
120
 
93
- def exactly(number)
94
- set_expected_yields_count(:==, number)
95
- self
121
+ # @api private
122
+ # @return [String]
123
+ def failure_message_when_negated
124
+ 'expected given block not to yield control' + failure_reason
96
125
  end
97
126
 
98
- def at_most(number)
99
- set_expected_yields_count(:<=, number)
100
- self
127
+ # @private
128
+ def supports_block_expectations?
129
+ true
101
130
  end
102
131
 
103
- def at_least(number)
104
- set_expected_yields_count(:>=, number)
105
- self
132
+ # @private
133
+ def supports_value_expectations?
134
+ false
106
135
  end
107
136
 
108
- def times
109
- self
110
- end
137
+ private
111
138
 
112
- def failure_message_for_should
113
- 'expected given block to yield control'.tap do |failure_message|
114
- failure_message << relativity_failure_message
115
- end
139
+ def failure_reason
140
+ return ' but was not a block' unless @probe.has_block?
141
+ return "#{count_expectation_description} but did not yield" if @probe.num_yields == 0
142
+ count_failure_reason('yielded')
116
143
  end
144
+ end
117
145
 
118
- def failure_message_for_should_not
119
- 'expected given block not to yield control'.tap do |failure_message|
120
- failure_message << relativity_failure_message
121
- end
146
+ # @api private
147
+ # Provides the implementation for `yield_with_no_args`.
148
+ # Not intended to be instantiated directly.
149
+ class YieldWithNoArgs < BaseMatcher
150
+ # @private
151
+ def matches?(block)
152
+ @probe = YieldProbe.probe(block)
153
+ return false unless @probe.has_block?
154
+ @probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty?
122
155
  end
123
156
 
124
- private
125
-
126
- def set_expected_yields_count(relativity, n)
127
- @expectation_type = relativity
128
- @expected_yields_count = case n
129
- when Numeric then n
130
- when :once then 1
131
- when :twice then 2
132
- end
157
+ # @private
158
+ def does_not_match?(block)
159
+ !matches?(block) && @probe.has_block?
133
160
  end
134
161
 
135
- def relativity_failure_message
136
- return '' unless @expected_yields_count
137
- " #{human_readable_expecation_type}#{human_readable_count}"
162
+ # @private
163
+ def failure_message
164
+ "expected given block to yield with no arguments, but #{positive_failure_reason}"
138
165
  end
139
166
 
140
- def human_readable_expecation_type
141
- case @expectation_type
142
- when :<= then 'at most '
143
- when :>= then 'at least '
144
- else ''
145
- end
167
+ # @private
168
+ def failure_message_when_negated
169
+ "expected given block not to yield with no arguments, but #{negative_failure_reason}"
146
170
  end
147
171
 
148
- def human_readable_count
149
- case @expected_yields_count
150
- when 1 then "once"
151
- when 2 then "twice"
152
- else "#{@expected_yields_count} times"
153
- end
172
+ # @private
173
+ def supports_block_expectations?
174
+ true
154
175
  end
155
- end
156
-
157
- class YieldWithNoArgs < BaseMatcher
158
176
 
159
- def matches?(block)
160
- @probe = YieldProbe.probe(block)
161
- @probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty?
177
+ # @private
178
+ def supports_value_expectations?
179
+ false
162
180
  end
163
181
 
164
- def failure_message_for_should
165
- "expected given block to yield with no arguments, but #{failure_reason}"
166
- end
182
+ private
167
183
 
168
- def failure_message_for_should_not
169
- "expected given block not to yield with no arguments, but did"
184
+ def positive_failure_reason
185
+ return 'was not a block' unless @probe.has_block?
186
+ return 'did not yield' if @probe.num_yields.zero?
187
+ "yielded with arguments: #{description_of @probe.single_yield_args}"
170
188
  end
171
189
 
172
- private
173
-
174
- def failure_reason
175
- if @probe.num_yields.zero?
176
- "did not yield"
177
- else
178
- "yielded with arguments: #{@probe.single_yield_args.inspect}"
179
- end
190
+ def negative_failure_reason
191
+ return 'was not a block' unless @probe.has_block?
192
+ 'did'
180
193
  end
181
194
  end
182
195
 
183
- class YieldWithArgs
196
+ # @api private
197
+ # Provides the implementation for `yield_with_args`.
198
+ # Not intended to be instantiated directly.
199
+ class YieldWithArgs < BaseMatcher
184
200
  def initialize(*args)
185
201
  @expected = args
186
202
  end
187
203
 
204
+ # @private
188
205
  def matches?(block)
189
- @probe = YieldProbe.probe(block)
190
- @actual = @probe.single_yield_args
191
- @probe.yielded_once?(:yield_with_args) && args_match?
206
+ @args_matched_when_yielded = true
207
+ @probe = YieldProbe.new(block) do
208
+ @actual = @probe.single_yield_args
209
+ @actual_formatted = actual_formatted
210
+ @args_matched_when_yielded &&= args_currently_match?
211
+ end
212
+ return false unless @probe.has_block?
213
+ @probe.probe
214
+ @probe.yielded_once?(:yield_with_args) && @args_matched_when_yielded
215
+ end
216
+
217
+ # @private
218
+ def does_not_match?(block)
219
+ !matches?(block) && @probe.has_block?
192
220
  end
193
- alias == matches?
194
221
 
195
- def failure_message_for_should
222
+ # @private
223
+ def failure_message
196
224
  "expected given block to yield with arguments, but #{positive_failure_reason}"
197
225
  end
198
226
 
199
- def failure_message_for_should_not
227
+ # @private
228
+ def failure_message_when_negated
200
229
  "expected given block not to yield with arguments, but #{negative_failure_reason}"
201
230
  end
202
231
 
232
+ # @private
203
233
  def description
204
- desc = "yield with args"
205
- desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")" unless @expected.empty?
234
+ desc = 'yield with args'
235
+ desc = "#{desc}(#{expected_arg_description})" unless @expected.empty?
206
236
  desc
207
237
  end
208
238
 
239
+ # @private
240
+ def supports_block_expectations?
241
+ true
242
+ end
243
+
244
+ # @private
245
+ def supports_value_expectations?
246
+ false
247
+ end
248
+
209
249
  private
210
250
 
211
251
  def positive_failure_reason
212
- if @probe.num_yields.zero?
213
- "did not yield"
214
- else
215
- @positive_args_failure
216
- end
252
+ return 'was not a block' unless @probe.has_block?
253
+ return 'did not yield' if @probe.num_yields.zero?
254
+ @positive_args_failure
255
+ end
256
+
257
+ def expected_arg_description
258
+ @expected.map { |e| description_of e }.join(', ')
217
259
  end
218
260
 
219
261
  def negative_failure_reason
220
- if all_args_match?
221
- "yielded with expected arguments" +
222
- "\nexpected not: #{@expected.inspect}" +
223
- "\n got: #{@actual.inspect} (compared using === and ==)"
262
+ if !@probe.has_block?
263
+ 'was not a block'
264
+ elsif @args_matched_when_yielded && !@expected.empty?
265
+ 'yielded with expected arguments' \
266
+ "\nexpected not: #{surface_descriptions_in(@expected).inspect}" \
267
+ "\n got: #{@actual_formatted}"
224
268
  else
225
- "did"
269
+ 'did'
226
270
  end
227
271
  end
228
272
 
229
- def args_match?
273
+ def args_currently_match?
230
274
  if @expected.empty? # expect {...}.to yield_with_args
231
- @positive_args_failure = "yielded with no arguments" if @actual.empty?
275
+ @positive_args_failure = 'yielded with no arguments' if @actual.empty?
232
276
  return !@actual.empty?
233
277
  end
234
278
 
235
- unless match = all_args_match?
236
- @positive_args_failure = "yielded with unexpected arguments" +
237
- "\nexpected: #{@expected.inspect}" +
238
- "\n got: #{@actual.inspect} (compared using === and ==)"
279
+ unless (match = all_args_match?)
280
+ @positive_args_failure = 'yielded with unexpected arguments' \
281
+ "\nexpected: #{surface_descriptions_in(@expected).inspect}" \
282
+ "\n got: #{@actual_formatted}"
239
283
  end
240
284
 
241
285
  match
242
286
  end
243
287
 
244
288
  def all_args_match?
245
- return false if @expected.size != @actual.size
246
-
247
- @expected.zip(@actual).all? do |expected, actual|
248
- expected === actual || actual == expected
249
- end
289
+ values_match?(@expected, @actual)
250
290
  end
251
291
  end
252
292
 
253
- class YieldSuccessiveArgs
293
+ # @api private
294
+ # Provides the implementation for `yield_successive_args`.
295
+ # Not intended to be instantiated directly.
296
+ class YieldSuccessiveArgs < BaseMatcher
254
297
  def initialize(*args)
255
298
  @expected = args
256
299
  end
257
300
 
301
+ # @private
258
302
  def matches?(block)
259
- @probe = YieldProbe.probe(block)
260
- @actual = @probe.successive_yield_args
261
- args_match?
303
+ @actual_formatted = []
304
+ @actual = []
305
+ args_matched_when_yielded = true
306
+ yield_count = 0
307
+
308
+ @probe = YieldProbe.probe(block) do |*arg_array|
309
+ arg_or_args = arg_array.size == 1 ? arg_array.first : arg_array
310
+ @actual_formatted << RSpec::Support::ObjectFormatter.format(arg_or_args)
311
+ @actual << arg_or_args
312
+ args_matched_when_yielded &&= values_match?(@expected[yield_count], arg_or_args)
313
+ yield_count += 1
314
+ end
315
+
316
+ return false unless @probe.has_block?
317
+ args_matched_when_yielded && yield_count == @expected.length
262
318
  end
263
- alias == matches?
264
319
 
265
- def failure_message_for_should
266
- "expected given block to yield successively with arguments, but yielded with unexpected arguments" +
267
- "\nexpected: #{@expected.inspect}" +
268
- "\n got: #{@actual.inspect} (compared using === and ==)"
320
+ def does_not_match?(block)
321
+ !matches?(block) && @probe.has_block?
269
322
  end
270
323
 
271
- def failure_message_for_should_not
272
- "expected given block not to yield successively with arguments, but yielded with expected arguments" +
273
- "\nexpected not: #{@expected.inspect}" +
274
- "\n got: #{@actual.inspect} (compared using === and ==)"
324
+ # @private
325
+ def failure_message
326
+ 'expected given block to yield successively with arguments, ' \
327
+ "but #{positive_failure_reason}"
275
328
  end
276
329
 
330
+ # @private
331
+ def failure_message_when_negated
332
+ 'expected given block not to yield successively with arguments, ' \
333
+ "but #{negative_failure_reason}"
334
+ end
335
+
336
+ # @private
277
337
  def description
278
- desc = "yield successive args"
279
- desc << "(" + @expected.map { |e| e.inspect }.join(", ") + ")"
280
- desc
338
+ "yield successive args(#{expected_arg_description})"
339
+ end
340
+
341
+ # @private
342
+ def supports_block_expectations?
343
+ true
344
+ end
345
+
346
+ # @private
347
+ def supports_value_expectations?
348
+ false
281
349
  end
282
350
 
283
351
  private
284
352
 
285
- def args_match?
286
- return false if @expected.size != @actual.size
353
+ def expected_arg_description
354
+ @expected.map { |e| description_of e }.join(', ')
355
+ end
287
356
 
288
- @expected.zip(@actual).all? do |expected, actual|
289
- expected === actual || actual == expected
290
- end
357
+ def positive_failure_reason
358
+ return 'was not a block' unless @probe.has_block?
359
+
360
+ 'yielded with unexpected arguments' \
361
+ "\nexpected: #{surface_descriptions_in(@expected).inspect}" \
362
+ "\n got: [#{@actual_formatted.join(", ")}]"
363
+ end
364
+
365
+ def negative_failure_reason
366
+ return 'was not a block' unless @probe.has_block?
367
+
368
+ 'yielded with expected arguments' \
369
+ "\nexpected not: #{surface_descriptions_in(@expected).inspect}" \
370
+ "\n got: [#{@actual_formatted.join(", ")}]"
291
371
  end
292
372
  end
293
373
  end
294
374
  end
295
375
  end
296
-
@@ -1,39 +1,53 @@
1
+ RSpec::Support.require_rspec_matchers "built_in/base_matcher"
2
+
1
3
  module RSpec
2
4
  module Matchers
5
+ # Container module for all built-in matchers. The matcher classes are here
6
+ # (rather than directly under `RSpec::Matchers`) in order to prevent name
7
+ # collisions, since `RSpec::Matchers` gets included into the user's namespace.
8
+ #
9
+ # Autoloading is used to delay when the matcher classes get loaded, allowing
10
+ # rspec-matchers to boot faster, and avoiding loading matchers the user is
11
+ # not using.
3
12
  module BuiltIn
4
- require 'rspec/matchers/built_in/base_matcher'
5
- autoload :BeAnInstanceOf, 'rspec/matchers/built_in/be_instance_of'
6
- autoload :Be, 'rspec/matchers/built_in/be'
7
- autoload :BeTrue, 'rspec/matchers/built_in/be'
8
- autoload :BeFalse, 'rspec/matchers/built_in/be'
9
- autoload :BeNil, 'rspec/matchers/built_in/be'
10
- autoload :BeComparedTo, 'rspec/matchers/built_in/be'
11
- autoload :BePredicate, 'rspec/matchers/built_in/be'
12
- autoload :BeAKindOf, 'rspec/matchers/built_in/be_kind_of'
13
- autoload :BeWithin, 'rspec/matchers/built_in/be_within'
14
- autoload :Change, 'rspec/matchers/built_in/change'
15
- autoload :Cover, 'rspec/matchers/built_in/cover' if (1..2).respond_to?(:cover?)
16
- autoload :Eq, 'rspec/matchers/built_in/eq'
17
- autoload :Eql, 'rspec/matchers/built_in/eql'
18
- autoload :Equal, 'rspec/matchers/built_in/equal'
19
- autoload :Exist, 'rspec/matchers/built_in/exist'
20
- autoload :Has, 'rspec/matchers/built_in/has'
21
- autoload :Have, 'rspec/matchers/built_in/have'
22
- autoload :Include, 'rspec/matchers/built_in/include'
23
- autoload :Match, 'rspec/matchers/built_in/match'
24
- autoload :MatchArray, 'rspec/matchers/built_in/match_array'
25
- autoload :RaiseError, 'rspec/matchers/built_in/raise_error'
26
- autoload :RespondTo, 'rspec/matchers/built_in/respond_to'
27
- autoload :StartWith, 'rspec/matchers/built_in/start_and_end_with'
28
- autoload :EndWith, 'rspec/matchers/built_in/start_and_end_with'
29
- autoload :Satisfy, 'rspec/matchers/built_in/satisfy'
30
- autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol'
31
- autoload :YieldControl, 'rspec/matchers/built_in/yield'
32
- autoload :YieldWithArgs, 'rspec/matchers/built_in/yield'
33
- autoload :YieldWithNoArgs, 'rspec/matchers/built_in/yield'
34
- autoload :YieldSuccessiveArgs, 'rspec/matchers/built_in/yield'
13
+ autoload :BeAKindOf, 'rspec/matchers/built_in/be_kind_of'
14
+ autoload :BeAnInstanceOf, 'rspec/matchers/built_in/be_instance_of'
15
+ autoload :BeBetween, 'rspec/matchers/built_in/be_between'
16
+ autoload :Be, 'rspec/matchers/built_in/be'
17
+ autoload :BeComparedTo, 'rspec/matchers/built_in/be'
18
+ autoload :BeFalsey, 'rspec/matchers/built_in/be'
19
+ autoload :BeHelpers, 'rspec/matchers/built_in/be'
20
+ autoload :BeNil, 'rspec/matchers/built_in/be'
21
+ autoload :BePredicate, 'rspec/matchers/built_in/has'
22
+ autoload :BeTruthy, 'rspec/matchers/built_in/be'
23
+ autoload :BeWithin, 'rspec/matchers/built_in/be_within'
24
+ autoload :Change, 'rspec/matchers/built_in/change'
25
+ autoload :Compound, 'rspec/matchers/built_in/compound'
26
+ autoload :ContainExactly, 'rspec/matchers/built_in/contain_exactly'
27
+ autoload :Cover, 'rspec/matchers/built_in/cover'
28
+ autoload :EndWith, 'rspec/matchers/built_in/start_or_end_with'
29
+ autoload :Eq, 'rspec/matchers/built_in/eq'
30
+ autoload :Eql, 'rspec/matchers/built_in/eql'
31
+ autoload :Equal, 'rspec/matchers/built_in/equal'
32
+ autoload :Exist, 'rspec/matchers/built_in/exist'
33
+ autoload :Has, 'rspec/matchers/built_in/has'
34
+ autoload :HaveAttributes, 'rspec/matchers/built_in/have_attributes'
35
+ autoload :Include, 'rspec/matchers/built_in/include'
36
+ autoload :All, 'rspec/matchers/built_in/all'
37
+ autoload :Match, 'rspec/matchers/built_in/match'
38
+ autoload :NegativeOperatorMatcher, 'rspec/matchers/built_in/operators'
39
+ autoload :OperatorMatcher, 'rspec/matchers/built_in/operators'
40
+ autoload :Output, 'rspec/matchers/built_in/output'
41
+ autoload :PositiveOperatorMatcher, 'rspec/matchers/built_in/operators'
42
+ autoload :RaiseError, 'rspec/matchers/built_in/raise_error'
43
+ autoload :RespondTo, 'rspec/matchers/built_in/respond_to'
44
+ autoload :Satisfy, 'rspec/matchers/built_in/satisfy'
45
+ autoload :StartWith, 'rspec/matchers/built_in/start_or_end_with'
46
+ autoload :ThrowSymbol, 'rspec/matchers/built_in/throw_symbol'
47
+ autoload :YieldControl, 'rspec/matchers/built_in/yield'
48
+ autoload :YieldSuccessiveArgs, 'rspec/matchers/built_in/yield'
49
+ autoload :YieldWithArgs, 'rspec/matchers/built_in/yield'
50
+ autoload :YieldWithNoArgs, 'rspec/matchers/built_in/yield'
35
51
  end
36
52
  end
37
53
  end
38
-
39
-