rspec-expectations 2.14.0 → 3.0.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 (143) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +369 -25
  4. data/License.txt +1 -0
  5. data/README.md +88 -15
  6. data/lib/rspec/{matchers → expectations}/configuration.rb +44 -14
  7. data/lib/rspec/expectations/expectation_target.rb +67 -33
  8. data/lib/rspec/expectations/fail_with.rb +11 -53
  9. data/lib/rspec/expectations/handler.rb +126 -31
  10. data/lib/rspec/expectations/minitest_integration.rb +16 -0
  11. data/lib/rspec/expectations/syntax.rb +60 -94
  12. data/lib/rspec/expectations/version.rb +1 -1
  13. data/lib/rspec/expectations.rb +45 -23
  14. data/lib/rspec/matchers/aliased_matcher.rb +41 -0
  15. data/lib/rspec/matchers/built_in/all.rb +78 -0
  16. data/lib/rspec/matchers/built_in/base_matcher.rb +63 -15
  17. data/lib/rspec/matchers/built_in/be.rb +170 -81
  18. data/lib/rspec/matchers/built_in/be_between.rb +77 -0
  19. data/lib/rspec/matchers/built_in/be_instance_of.rb +11 -3
  20. data/lib/rspec/matchers/built_in/be_kind_of.rb +5 -0
  21. data/lib/rspec/matchers/built_in/be_within.rb +39 -15
  22. data/lib/rspec/matchers/built_in/change.rb +273 -80
  23. data/lib/rspec/matchers/built_in/compound.rb +122 -0
  24. data/lib/rspec/matchers/built_in/contain_exactly.rb +256 -0
  25. data/lib/rspec/matchers/built_in/cover.rb +3 -0
  26. data/lib/rspec/matchers/built_in/eq.rb +60 -6
  27. data/lib/rspec/matchers/built_in/eql.rb +17 -5
  28. data/lib/rspec/matchers/built_in/equal.rb +55 -21
  29. data/lib/rspec/matchers/built_in/exist.rb +74 -10
  30. data/lib/rspec/matchers/built_in/has.rb +71 -15
  31. data/lib/rspec/matchers/built_in/include.rb +64 -27
  32. data/lib/rspec/matchers/built_in/match.rb +19 -1
  33. data/lib/rspec/matchers/built_in/operators.rb +119 -0
  34. data/lib/rspec/matchers/built_in/output.rb +150 -0
  35. data/lib/rspec/matchers/built_in/raise_error.rb +84 -42
  36. data/lib/rspec/matchers/built_in/respond_to.rb +42 -20
  37. data/lib/rspec/matchers/built_in/satisfy.rb +19 -3
  38. data/lib/rspec/matchers/built_in/start_and_end_with.rb +54 -18
  39. data/lib/rspec/matchers/built_in/throw_symbol.rb +38 -8
  40. data/lib/rspec/matchers/built_in/yield.rb +175 -68
  41. data/lib/rspec/matchers/built_in.rb +45 -33
  42. data/lib/rspec/matchers/composable.rb +179 -0
  43. data/lib/rspec/matchers/dsl.rb +362 -5
  44. data/lib/rspec/matchers/generated_descriptions.rb +13 -6
  45. data/lib/rspec/matchers/matcher_delegator.rb +37 -0
  46. data/lib/rspec/matchers/pretty.rb +27 -20
  47. data/lib/rspec/matchers.rb +361 -136
  48. data.tar.gz.sig +1 -0
  49. metadata +99 -215
  50. metadata.gz.sig +0 -0
  51. data/features/README.md +0 -48
  52. data/features/Upgrade.md +0 -53
  53. data/features/built_in_matchers/README.md +0 -90
  54. data/features/built_in_matchers/be.feature +0 -175
  55. data/features/built_in_matchers/be_within.feature +0 -48
  56. data/features/built_in_matchers/cover.feature +0 -47
  57. data/features/built_in_matchers/end_with.feature +0 -48
  58. data/features/built_in_matchers/equality.feature +0 -139
  59. data/features/built_in_matchers/exist.feature +0 -45
  60. data/features/built_in_matchers/expect_change.feature +0 -59
  61. data/features/built_in_matchers/expect_error.feature +0 -144
  62. data/features/built_in_matchers/have.feature +0 -109
  63. data/features/built_in_matchers/include.feature +0 -174
  64. data/features/built_in_matchers/match.feature +0 -52
  65. data/features/built_in_matchers/operators.feature +0 -227
  66. data/features/built_in_matchers/predicates.feature +0 -137
  67. data/features/built_in_matchers/respond_to.feature +0 -84
  68. data/features/built_in_matchers/satisfy.feature +0 -33
  69. data/features/built_in_matchers/start_with.feature +0 -48
  70. data/features/built_in_matchers/throw_symbol.feature +0 -91
  71. data/features/built_in_matchers/types.feature +0 -116
  72. data/features/built_in_matchers/yield.feature +0 -161
  73. data/features/custom_matchers/access_running_example.feature +0 -53
  74. data/features/custom_matchers/define_diffable_matcher.feature +0 -27
  75. data/features/custom_matchers/define_matcher.feature +0 -368
  76. data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
  77. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
  78. data/features/customized_message.feature +0 -22
  79. data/features/diffing.feature +0 -85
  80. data/features/implicit_docstrings.feature +0 -52
  81. data/features/step_definitions/additional_cli_steps.rb +0 -22
  82. data/features/support/env.rb +0 -14
  83. data/features/syntax_configuration.feature +0 -71
  84. data/features/test_frameworks/test_unit.feature +0 -44
  85. data/lib/rspec/expectations/deprecation.rb +0 -17
  86. data/lib/rspec/expectations/differ.rb +0 -133
  87. data/lib/rspec/expectations/errors.rb +0 -9
  88. data/lib/rspec/expectations/extensions/array.rb +0 -9
  89. data/lib/rspec/expectations/extensions/object.rb +0 -29
  90. data/lib/rspec/expectations/extensions.rb +0 -2
  91. data/lib/rspec/matchers/be_close.rb +0 -9
  92. data/lib/rspec/matchers/built_in/have.rb +0 -124
  93. data/lib/rspec/matchers/built_in/match_array.rb +0 -51
  94. data/lib/rspec/matchers/compatibility.rb +0 -14
  95. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  96. data/lib/rspec/matchers/matcher.rb +0 -300
  97. data/lib/rspec/matchers/method_missing.rb +0 -12
  98. data/lib/rspec/matchers/operator_matcher.rb +0 -109
  99. data/lib/rspec/matchers/test_unit_integration.rb +0 -11
  100. data/lib/rspec-expectations.rb +0 -1
  101. data/spec/rspec/expectations/differ_spec.rb +0 -192
  102. data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
  103. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  104. data/spec/rspec/expectations/fail_with_spec.rb +0 -114
  105. data/spec/rspec/expectations/handler_spec.rb +0 -227
  106. data/spec/rspec/expectations/syntax_spec.rb +0 -139
  107. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  108. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  109. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  110. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  111. data/spec/rspec/matchers/be_spec.rb +0 -516
  112. data/spec/rspec/matchers/be_within_spec.rb +0 -137
  113. data/spec/rspec/matchers/change_spec.rb +0 -553
  114. data/spec/rspec/matchers/configuration_spec.rb +0 -206
  115. data/spec/rspec/matchers/cover_spec.rb +0 -69
  116. data/spec/rspec/matchers/description_generation_spec.rb +0 -190
  117. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  118. data/spec/rspec/matchers/eq_spec.rb +0 -60
  119. data/spec/rspec/matchers/eql_spec.rb +0 -41
  120. data/spec/rspec/matchers/equal_spec.rb +0 -78
  121. data/spec/rspec/matchers/exist_spec.rb +0 -124
  122. data/spec/rspec/matchers/has_spec.rb +0 -122
  123. data/spec/rspec/matchers/have_spec.rb +0 -455
  124. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  125. data/spec/rspec/matchers/include_spec.rb +0 -531
  126. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  127. data/spec/rspec/matchers/match_spec.rb +0 -61
  128. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  129. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  130. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  131. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  132. data/spec/rspec/matchers/raise_error_spec.rb +0 -485
  133. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  134. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  135. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  136. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  137. data/spec/rspec/matchers/yield_spec.rb +0 -514
  138. data/spec/spec_helper.rb +0 -54
  139. data/spec/support/classes.rb +0 -56
  140. data/spec/support/in_sub_process.rb +0 -38
  141. data/spec/support/matchers.rb +0 -22
  142. data/spec/support/ruby_version.rb +0 -10
  143. data/spec/support/shared_examples.rb +0 -13
@@ -1,29 +1,31 @@
1
- require 'rspec/matchers/extensions/instance_eval_with_args'
2
- require 'rspec/matchers/pretty'
3
-
4
- require 'rspec/matchers/built_in'
5
- require 'rspec/matchers/matcher'
6
- require 'rspec/matchers/operator_matcher'
7
- require 'rspec/matchers/be_close'
8
-
9
- require 'rspec/matchers/generated_descriptions'
10
- require 'rspec/matchers/method_missing'
11
- require 'rspec/matchers/compatibility'
12
- require 'rspec/matchers/dsl'
13
- require 'rspec/matchers/test_unit_integration'
14
-
1
+ require 'rspec/support'
2
+ RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) }
3
+
4
+ %w[
5
+ pretty
6
+ composable
7
+ built_in
8
+ generated_descriptions
9
+ dsl
10
+ matcher_delegator
11
+ aliased_matcher
12
+ ].each { |file| RSpec::Support.require_rspec_matchers(file) }
13
+
14
+ # RSpec's top level namespace. All of rspec-expectations is contained
15
+ # in the `RSpec::Expectations` and `RSpec::Matchers` namespaces.
15
16
  module RSpec
16
17
  # RSpec::Matchers provides a number of useful matchers we use to define
17
18
  # expectations. A matcher is any object that responds to the following:
18
19
  #
19
20
  # matches?(actual)
20
- # failure_message_for_should
21
+ # failure_message
21
22
  #
22
23
  # These methods are also part of the matcher protocol, but are optional:
23
24
  #
24
25
  # does_not_match?(actual)
25
- # failure_message_for_should_not
26
+ # failure_message_when_negated
26
27
  # description
28
+ # supports_block_expectations?
27
29
  #
28
30
  # ## Predicates
29
31
  #
@@ -61,6 +63,12 @@ module RSpec
61
63
  # You can use this feature to invoke any predicate that begins with "has_", whether it is
62
64
  # part of the Ruby libraries (like `Hash#has_key?`) or a method you wrote on your own class.
63
65
  #
66
+ # Note that RSpec does not provide composable aliases for these dynamic predicate
67
+ # matchers. You can easily define your own aliases, though:
68
+ #
69
+ # RSpec::Matchers.alias_matcher :a_user_who_is_an_admin, :be_an_admin
70
+ # expect(user_list).to include(a_user_who_is_an_admin)
71
+ #
64
72
  # ## Custom Matchers
65
73
  #
66
74
  # When you find that none of the stock matchers provide a natural feeling
@@ -100,11 +108,11 @@ module RSpec
100
108
  # player.in_zone?(zone)
101
109
  # end
102
110
  #
103
- # failure_message_for_should do |player|
111
+ # failure_message do |player|
104
112
  # # generate and return the appropriate string.
105
113
  # end
106
114
  #
107
- # failure_message_for_should_not do |player|
115
+ # failure_message_when_negated do |player|
108
116
  # # generate and return the appropriate string.
109
117
  # end
110
118
  #
@@ -115,8 +123,8 @@ module RSpec
115
123
  #
116
124
  # Each of the message-generation methods has access to the block arguments
117
125
  # passed to the <tt>create</tt> method (in this case, <tt>zone</tt>). The
118
- # failure message methods (<tt>failure_message_for_should</tt> and
119
- # <tt>failure_message_for_should_not</tt>) are passed the actual value (the
126
+ # failure message methods (<tt>failure_message</tt> and
127
+ # <tt>failure_message_when_negated</tt>) are passed the actual value (the
120
128
  # receiver of <tt>expect(..)</tt> or <tt>expect(..).not_to</tt>).
121
129
  #
122
130
  # ### Custom Matcher from scratch
@@ -133,11 +141,11 @@ module RSpec
133
141
  # @target.current_zone.eql?(Zone.new(@expected))
134
142
  # end
135
143
  #
136
- # def failure_message_for_should
144
+ # def failure_message
137
145
  # "expected #{@target.inspect} to be in Zone #{@expected}"
138
146
  # end
139
147
  #
140
- # def failure_message_for_should_not
148
+ # def failure_message_when_negated
141
149
  # "expected #{@target.inspect} not to be in Zone #{@expected}"
142
150
  # end
143
151
  # end
@@ -173,34 +181,108 @@ module RSpec
173
181
  # RSpec::configure do |config|
174
182
  # config.include(CustomGameMatchers)
175
183
  # end
184
+ #
185
+ # ### Making custom matchers composable
186
+ #
187
+ # RSpec's built-in matchers are designed to be composed, in expressions like:
188
+ #
189
+ # expect(["barn", 2.45]).to contain_exactly(
190
+ # a_value_within(0.1).of(2.5),
191
+ # a_string_starting_with("bar")
192
+ # )
193
+ #
194
+ # Custom matchers can easily participate in composed matcher expressions like these.
195
+ # Include {RSpec::Matchers::Composable} in your custom matcher to make it support
196
+ # being composed (matchers defined using the DSL have this included automatically).
197
+ # Within your matcher's `matches?` method (or the `match` block, if using the DSL),
198
+ # use `values_match?(expected, actual)` rather than `expected == actual`.
199
+ # Under the covers, `values_match?` is able to match arbitrary
200
+ # nested data structures containing a mix of both matchers and non-matcher objects.
201
+ # It uses `===` and `==` to perform the matching, considering the values to
202
+ # match if either returns `true`. The `Composable` mixin also provides some helper
203
+ # methods for surfacing the matcher descriptions within your matcher's description
204
+ # or failure messages.
205
+ #
206
+ # RSpec's built-in matchers each have a number of aliases that rephrase the matcher
207
+ # from a verb phrase (such as `be_within`) to a noun phrase (such as `a_value_within`),
208
+ # which reads better when the matcher is passed as an argument in a composed matcher
209
+ # expressions, and also uses the noun-phrase wording in the matcher's `description`,
210
+ # for readable failure messages. You can alias your custom matchers in similar fashion
211
+ # using {RSpec::Matchers.alias_matcher}.
176
212
  module Matchers
177
- # @api private
178
- def self.is_a_matcher?(obj)
179
- return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj
180
- return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
181
- return false unless obj.respond_to?(:matches?)
182
-
183
- obj.respond_to?(:failure_message_for_should) || obj.respond_to?(:failure_message)
213
+ # @method expect
214
+ # Supports `expect(actual).to matcher` syntax by wrapping `actual` in an
215
+ # `ExpectationTarget`.
216
+ # @example
217
+ # expect(actual).to eq(expected)
218
+ # expect(actual).not_to eq(expected)
219
+ # @return [ExpectationTarget]
220
+ # @see ExpectationTarget#to
221
+ # @see ExpectationTarget#not_to
222
+
223
+ # Defines a matcher alias. The returned matcher's `description` will be overriden
224
+ # to reflect the phrasing of the new name, which will be used in failure messages
225
+ # when passed as an argument to another matcher in a composed matcher expression.
226
+ #
227
+ # @param new_name [Symbol] the new name for the matcher
228
+ # @param old_name [Symbol] the original name for the matcher
229
+ # @yield [String] optional block that, when given is used to define the overriden
230
+ # description. The yielded arg is the original description. If no block is
231
+ # provided, a default description override is used based on the old and
232
+ # new names.
233
+ #
234
+ # @example
235
+ #
236
+ # RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to
237
+ # sum_to(3).description # => "sum to 3"
238
+ # a_list_that_sums_to(3).description # => "a list that sums to 3"
239
+ #
240
+ # @example
241
+ #
242
+ # RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description|
243
+ # description.sub("be sorted by", "a list sorted by")
244
+ # end
245
+ #
246
+ # be_sorted_by(:age).description # => "be sorted by age"
247
+ # a_list_sorted_by(:age).description # => "a list sorted by age"
248
+ #
249
+ # @!macro [attach] alias_matcher
250
+ # @!parse
251
+ # alias $1 $2
252
+ def self.alias_matcher(new_name, old_name, &description_override)
253
+ description_override ||= lambda do |old_desc|
254
+ old_desc.gsub(Pretty.split_words(old_name), Pretty.split_words(new_name))
255
+ end
256
+
257
+ define_method(new_name) do |*args, &block|
258
+ matcher = __send__(old_name, *args, &block)
259
+ AliasedMatcher.new(matcher, description_override)
260
+ end
184
261
  end
185
262
 
186
263
  # Passes if actual is truthy (anything but false or nil)
187
- def be_true
188
- BuiltIn::BeTrue.new
264
+ def be_truthy
265
+ BuiltIn::BeTruthy.new
189
266
  end
267
+ alias_matcher :a_truthy_value, :be_truthy
190
268
 
191
- # Passes if actual is falsy (false or nil)
192
- def be_false
193
- BuiltIn::BeFalse.new
269
+ # Passes if actual is falsey (false or nil)
270
+ def be_falsey
271
+ BuiltIn::BeFalsey.new
194
272
  end
273
+ alias_matcher :be_falsy, :be_falsey
274
+ alias_matcher :a_falsey_value, :be_falsey
275
+ alias_matcher :a_falsy_value, :be_falsey
195
276
 
196
277
  # Passes if actual is nil
197
278
  def be_nil
198
279
  BuiltIn::BeNil.new
199
280
  end
281
+ alias_matcher :a_nil_value, :be_nil
200
282
 
201
283
  # @example
202
- # expect(actual).to be_true
203
- # expect(actual).to be_false
284
+ # expect(actual).to be_truthy
285
+ # expect(actual).to be_falsey
204
286
  # expect(actual).to be_nil
205
287
  # expect(actual).to be_[arbitrary_predicate](*args)
206
288
  # expect(actual).not_to be_nil
@@ -222,12 +304,12 @@ module RSpec
222
304
  args.empty? ?
223
305
  Matchers::BuiltIn::Be.new : equal(*args)
224
306
  end
307
+ alias_matcher :a_value, :be
225
308
 
226
309
  # passes if target.kind_of?(klass)
227
310
  def be_a(klass)
228
311
  be_a_kind_of(klass)
229
312
  end
230
-
231
313
  alias_method :be_an, :be_a
232
314
 
233
315
  # Passes if actual.instance_of?(expected)
@@ -240,8 +322,8 @@ module RSpec
240
322
  def be_an_instance_of(expected)
241
323
  BuiltIn::BeAnInstanceOf.new(expected)
242
324
  end
243
-
244
- alias_method :be_instance_of, :be_an_instance_of
325
+ alias_method :be_instance_of, :be_an_instance_of
326
+ alias_matcher :an_instance_of, :be_an_instance_of
245
327
 
246
328
  # Passes if actual.kind_of?(expected)
247
329
  #
@@ -253,8 +335,25 @@ module RSpec
253
335
  def be_a_kind_of(expected)
254
336
  BuiltIn::BeAKindOf.new(expected)
255
337
  end
338
+ alias_method :be_kind_of, :be_a_kind_of
339
+ alias_matcher :a_kind_of, :be_a_kind_of
256
340
 
257
- alias_method :be_kind_of, :be_a_kind_of
341
+ # Passes if actual.between?(min, max). Works with any Comparable object,
342
+ # including String, Symbol, Time, or Numeric (Fixnum, Bignum, Integer,
343
+ # Float, Complex, and Rational).
344
+ #
345
+ # By default, `be_between` is inclusive (i.e. passes when given either the max or min value),
346
+ # but you can make it `exclusive` by chaining that off the matcher.
347
+ #
348
+ # @example
349
+ #
350
+ # expect(5).to be_between(1, 10)
351
+ # expect(11).not_to be_between(1, 10)
352
+ # expect(10).not_to be_between(1, 10).exclusive
353
+ def be_between(min, max)
354
+ BuiltIn::BeBetween.new(min, max)
355
+ end
356
+ alias_matcher :a_value_between, :be_between
258
357
 
259
358
  # Passes if actual == expected +/- delta
260
359
  #
@@ -265,6 +364,8 @@ module RSpec
265
364
  def be_within(delta)
266
365
  BuiltIn::BeWithin.new(delta)
267
366
  end
367
+ alias_matcher :a_value_within, :be_within
368
+ alias_matcher :within, :be_within
268
369
 
269
370
  # Applied to a proc, specifies that its execution will cause some value to
270
371
  # change.
@@ -275,9 +376,18 @@ module RSpec
275
376
  # You can either pass <tt>receiver</tt> and <tt>message</tt>, or a block,
276
377
  # but not both.
277
378
  #
278
- # When passing a block, it must use the <tt>{ ... }</tt> format, not
279
- # do/end, as <tt>{ ... }</tt> binds to the +change+ method, whereas do/end
280
- # would errantly bind to the +expect(..)+ or +expect(..).not_to+ method.
379
+ # When passing a block, it must use the `{ ... }` format, not
380
+ # do/end, as `{ ... }` binds to the `change` method, whereas do/end
381
+ # would errantly bind to the `expect(..).to` or `expect(...).not_to` method.
382
+ #
383
+ # You can chain any of the following off of the end to specify details
384
+ # about the change:
385
+ #
386
+ # * `by`
387
+ # * `by_at_least`
388
+ # * `by_at_most`
389
+ # * `from`
390
+ # * `to`
281
391
  #
282
392
  # @example
283
393
  #
@@ -305,7 +415,7 @@ module RSpec
305
415
  # string = "string"
306
416
  # expect {
307
417
  # string
308
- # }.not_to change { string }
418
+ # }.not_to change { string }.from("string")
309
419
  #
310
420
  # expect {
311
421
  # person.happy_birthday
@@ -326,15 +436,40 @@ module RSpec
326
436
  #
327
437
  # == Notes
328
438
  #
329
- # Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after it
330
- # evaluates the block passed to <tt>expect</tt>.
439
+ # Evaluates `receiver.message` or `block` before and after it
440
+ # evaluates the block passed to `expect`.
331
441
  #
332
- # <tt>expect( ... ).not_to change</tt> only supports the form with no subsequent
333
- # calls to <tt>by</tt>, <tt>by_at_least</tt>, <tt>by_at_most</tt>,
334
- # <tt>to</tt> or <tt>from</tt>.
442
+ # `expect( ... ).not_to change` supports the form that specifies `from`
443
+ # (which specifies what you expect the starting, unchanged value to be)
444
+ # but does not support forms with subsequent calls to `by`, `by_at_least`,
445
+ # `by_at_most` or `to`.
335
446
  def change(receiver=nil, message=nil, &block)
336
447
  BuiltIn::Change.new(receiver, message, &block)
337
448
  end
449
+ alias_matcher :a_block_changing, :change
450
+ alias_matcher :changing, :change
451
+
452
+ # Passes if actual contains all of the expected regardless of order.
453
+ # This works for collections. Pass in multiple args and it will only
454
+ # pass if all args are found in collection.
455
+ #
456
+ # @note This is also available using the `=~` operator with `should`,
457
+ # but `=~` is not supported with `expect`.
458
+ #
459
+ # @note This matcher only supports positive expectations.
460
+ # `expect(...).not_to contain_exactly(other_array)` is not supported.
461
+ #
462
+ # @example
463
+ #
464
+ # expect([1, 2, 3]).to contain_exactly(1, 2, 3)
465
+ # expect([1, 2, 3]).to contain_exactly(1, 3, 2)
466
+ #
467
+ # @see #match_array
468
+ def contain_exactly(*items)
469
+ BuiltIn::ContainExactly.new(items)
470
+ end
471
+ alias_matcher :a_collection_containing_exactly, :contain_exactly
472
+ alias_matcher :containing_exactly, :contain_exactly
338
473
 
339
474
  # Passes if actual covers expected. This works for
340
475
  # Ranges. You can also pass in multiple args
@@ -350,7 +485,9 @@ module RSpec
350
485
  # ### Warning:: Ruby >= 1.9 only
351
486
  def cover(*values)
352
487
  BuiltIn::Cover.new(*values)
353
- end if (1..2).respond_to?(:cover?)
488
+ end
489
+ alias_matcher :a_range_covering, :cover
490
+ alias_matcher :covering, :cover
354
491
 
355
492
  # Matches if the actual value ends with the expected value(s). In the case
356
493
  # of a string, matches against the last `expected.length` characters of the
@@ -365,6 +502,9 @@ module RSpec
365
502
  def end_with(*expected)
366
503
  BuiltIn::EndWith.new(*expected)
367
504
  end
505
+ alias_matcher :a_collection_ending_with, :end_with
506
+ alias_matcher :a_string_ending_with, :end_with
507
+ alias_matcher :ending_with, :end_with
368
508
 
369
509
  # Passes if <tt>actual == expected</tt>.
370
510
  #
@@ -378,8 +518,10 @@ module RSpec
378
518
  def eq(expected)
379
519
  BuiltIn::Eq.new(expected)
380
520
  end
521
+ alias_matcher :an_object_eq_to, :eq
522
+ alias_matcher :eq_to, :eq
381
523
 
382
- # Passes if +actual.eql?(expected)+
524
+ # Passes if `actual.eql?(expected)`
383
525
  #
384
526
  # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more
385
527
  # information about equality in Ruby.
@@ -391,6 +533,8 @@ module RSpec
391
533
  def eql(expected)
392
534
  BuiltIn::Eql.new(expected)
393
535
  end
536
+ alias_matcher :an_object_eql_to, :eql
537
+ alias_matcher :eql_to, :eql
394
538
 
395
539
  # Passes if <tt>actual.equal?(expected)</tt> (object identity).
396
540
  #
@@ -404,6 +548,8 @@ module RSpec
404
548
  def equal(expected)
405
549
  BuiltIn::Equal.new(expected)
406
550
  end
551
+ alias_matcher :an_object_equal_to, :equal
552
+ alias_matcher :equal_to, :equal
407
553
 
408
554
  # Passes if `actual.exist?` or `actual.exists?`
409
555
  #
@@ -412,99 +558,131 @@ module RSpec
412
558
  def exist(*args)
413
559
  BuiltIn::Exist.new(*args)
414
560
  end
561
+ alias_matcher :an_object_existing, :exist
562
+ alias_matcher :existing, :exist
415
563
 
416
- # Passes if receiver is a collection with the submitted number of items OR
417
- # if the receiver OWNS a collection with the submitted number of items.
418
- #
419
- # If the receiver OWNS the collection, you must use the name of the
420
- # collection. So if a `Team` instance has a collection named `#players`,
421
- # you must use that name to set the expectation.
564
+ # Passes if actual includes expected. This works for
565
+ # collections and Strings. You can also pass in multiple args
566
+ # and it will only pass if all args are found in collection.
422
567
  #
423
- # If the receiver IS the collection, you can use any name you like for
424
- # `named_collection`. We'd recommend using either "elements", "members", or
425
- # "items" as these are all standard ways of describing the things IN a
426
- # collection.
568
+ # @example
427
569
  #
428
- # This also works for Strings, letting you set expectations about their
429
- # lengths.
570
+ # expect([1,2,3]).to include(3)
571
+ # expect([1,2,3]).to include(2,3)
572
+ # expect([1,2,3]).to include(2,3,4) # fails
573
+ # expect([1,2,3]).not_to include(4)
574
+ # expect("spread").to include("read")
575
+ # expect("spread").not_to include("red")
576
+ def include(*expected)
577
+ BuiltIn::Include.new(*expected)
578
+ end
579
+ alias_matcher :a_collection_including, :include
580
+ alias_matcher :a_string_including, :include
581
+ alias_matcher :a_hash_including, :include
582
+ alias_matcher :including, :include
583
+
584
+ # Passes if actual all expected objects pass. This works for
585
+ # any enumerable object.
430
586
  #
431
587
  # @example
432
588
  #
433
- # # Passes if team.players.size == 11
434
- # expect(team).to have(11).players
589
+ # expect([1, 3, 5]).to all be_odd
590
+ # expect([1, 3, 6]).to all be_odd # fails
435
591
  #
436
- # # Passes if [1,2,3].length == 3
437
- # expect([1,2,3]).to have(3).items #"items" is pure sugar
592
+ # @note The negative form `not_to all` is not supported. Instead
593
+ # use `not_to include` or pass a negative form of a matcher
594
+ # as the argument (e.g. `all exclude(:foo)`).
438
595
  #
439
- # # Passes if ['a', 'b', 'c'].count == 3
440
- # expect([1,2,3]).to have(3).items #"items" is pure sugar
596
+ # @note You can also use this with compound matchers as well.
441
597
  #
442
- # # Passes if "this string".length == 11
443
- # expect("this string").to have(11).characters #"characters" is pure sugar
444
- def have(n)
445
- BuiltIn::Have.new(n)
598
+ # @example
599
+ # expect([1, 3, 5]).to all( be_odd.and be_an(Integer) )
600
+ def all(expected)
601
+ BuiltIn::All.new(expected)
446
602
  end
447
- alias :have_exactly :have
448
603
 
449
- # Exactly like have() with >=.
604
+ # Given a `Regexp` or `String`, passes if `actual.match(pattern)`
605
+ # Given an arbitrary nested data structure (e.g. arrays and hashes),
606
+ # matches if `expected === actual` || `actual == expected` for each
607
+ # pair of elements.
450
608
  #
451
609
  # @example
452
- # expect("this").to have_at_least(3).letters
453
610
  #
454
- # ### Warning:
611
+ # expect(email).to match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
612
+ # expect(email).to match("@example.com")
455
613
  #
456
- # `expect(..).not_to have_at_least` is not supported
457
- def have_at_least(n)
458
- BuiltIn::Have.new(n, :at_least)
614
+ # @example
615
+ #
616
+ # hash = {
617
+ # :a => {
618
+ # :b => ["foo", 5],
619
+ # :c => { :d => 2.05 }
620
+ # }
621
+ # }
622
+ #
623
+ # expect(hash).to match(
624
+ # :a => {
625
+ # :b => a_collection_containing_exactly(
626
+ # a_string_starting_with("f"),
627
+ # an_instance_of(Fixnum)
628
+ # ),
629
+ # :c => { :d => (a_value < 3) }
630
+ # }
631
+ # )
632
+ #
633
+ # @note The `match_regex` alias is deprecated and is not recommended for use.
634
+ # It was added in 2.12.1 to facilitate its use from within custom
635
+ # matchers (due to how the custom matcher DSL was evaluated in 2.x,
636
+ # `match` could not be used there), but is no longer needed in 3.x.
637
+ def match(expected)
638
+ BuiltIn::Match.new(expected)
459
639
  end
640
+ alias_matcher :match_regex, :match
641
+ alias_matcher :an_object_matching, :match
642
+ alias_matcher :a_string_matching, :match
643
+ alias_matcher :matching, :match
460
644
 
461
- # Exactly like have() with <=.
645
+ # An alternate form of `contain_exactly` that accepts
646
+ # the expected contents as a single array arg rather
647
+ # that splatted out as individual items.
462
648
  #
463
649
  # @example
464
- # expect("this").to have_at_most(4).letters
465
650
  #
466
- # ### Warning:
651
+ # expect(results).to contain_exactly(1, 2)
652
+ # # is identical to:
653
+ # expect(results).to match_array([1, 2])
467
654
  #
468
- # `expect(..).not_to have_at_most` is not supported
469
- def have_at_most(n)
470
- BuiltIn::Have.new(n, :at_most)
655
+ # @see #contain_exactly
656
+ def match_array(items)
657
+ contain_exactly(*items)
471
658
  end
472
659
 
473
- # Passes if actual includes expected. This works for
474
- # collections and Strings. You can also pass in multiple args
475
- # and it will only pass if all args are found in collection.
660
+ # With no arg, passes if the block outputs `to_stdout` or `to_stderr`.
661
+ # With a string, passes if the blocks outputs that specific string `to_stdout` or `to_stderr`.
662
+ # With a regexp or matcher, passes if the blocks outputs a string `to_stdout` or `to_stderr` that matches.
476
663
  #
477
664
  # @example
478
665
  #
479
- # expect([1,2,3]).to include(3)
480
- # expect([1,2,3]).to include(2,3)
481
- # expect([1,2,3]).to include(2,3,4) # fails
482
- # expect([1,2,3]).not_to include(4)
483
- # expect("spread").to include("read")
484
- # expect("spread").not_to include("red")
485
- def include(*expected)
486
- BuiltIn::Include.new(*expected)
487
- end
488
-
489
- # Given a Regexp or String, passes if actual.match(pattern)
666
+ # expect { print 'foo' }.to output.to_stdout
667
+ # expect { print 'foo' }.to output('foo').to_stdout
668
+ # expect { print 'foo' }.to output(/foo/).to_stdout
490
669
  #
491
- # @example
670
+ # expect { do_something }.to_not output.to_stdout
492
671
  #
493
- # expect(email).to match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
494
- # expect(email).to match("@example.com")
495
- # expect(zipcode).to match_regex(/\A\d{5}(-\d{4})?\z/)
496
- # expect(zipcode).to match_regex("90210")
672
+ # expect { warn('foo') }.to output.to_stderr
673
+ # expect { warn('foo') }.to output('foo').to_stderr
674
+ # expect { warn('foo') }.to output(/foo/).to_stderr
497
675
  #
498
- # @note Due to Ruby's method dispatch mechanism, using the `#match` matcher
499
- # within a custom matcher defined via the matcher DSL
500
- # (`RSpec::Matcher.define`) will result Ruby calling the wrong `#match`
501
- # method and raising an `ArgumentError`. Instead, use the aliased
502
- # `#match_regex` method.
503
- def match(expected)
504
- BuiltIn::Match.new(expected)
676
+ # expect { do_something }.to_not output.to_stderr
677
+ #
678
+ # @note This matcher works by temporarily replacing `$stdout` or `$stderr`,
679
+ # so it's not able to intercept stream output that explicitly uses `STDOUT`/`STDERR`
680
+ # or that uses a reference to `$stdout`/`$stderr` that was stored before the
681
+ # matcher is used.
682
+ def output(expected=nil)
683
+ BuiltIn::Output.new(expected)
505
684
  end
506
-
507
- alias_method :match_regex, :match
685
+ alias_matcher :a_block_outputting, :output
508
686
 
509
687
  # With no args, matches if any error is raised.
510
688
  # With a named error, matches only if that specific error is raised.
@@ -521,25 +699,31 @@ module RSpec
521
699
  # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, /oo ri/)
522
700
  #
523
701
  # expect { do_something_risky }.not_to raise_error
524
- # expect { do_something_risky }.not_to raise_error(PoorRiskDecisionError)
525
- # expect { do_something_risky }.not_to raise_error(PoorRiskDecisionError, "that was too risky")
526
- # expect { do_something_risky }.not_to raise_error(PoorRiskDecisionError, /oo ri/)
527
702
  def raise_error(error=Exception, message=nil, &block)
528
703
  BuiltIn::RaiseError.new(error, message, &block)
529
704
  end
705
+ alias_method :raise_exception, :raise_error
530
706
 
531
- alias_method :raise_exception, :raise_error
707
+ alias_matcher :a_block_raising, :raise_error do |desc|
708
+ desc.sub("raise", "a block raising")
709
+ end
710
+
711
+ alias_matcher :raising, :raise_error do |desc|
712
+ desc.sub("raise", "raising")
713
+ end
532
714
 
533
715
  # Matches if the target object responds to all of the names
534
716
  # provided. Names can be Strings or Symbols.
535
717
  #
536
718
  # @example
537
719
  #
538
- # expect("string").to respond_to(:length)
720
+ # expect("string").to respond_to(:length)
539
721
  #
540
722
  def respond_to(*names)
541
723
  BuiltIn::RespondTo.new(*names)
542
724
  end
725
+ alias_matcher :an_object_responding_to, :respond_to
726
+ alias_matcher :responding_to, :respond_to
543
727
 
544
728
  # Passes if the submitted block returns true. Yields target to the
545
729
  # block.
@@ -557,6 +741,8 @@ module RSpec
557
741
  def satisfy(&block)
558
742
  BuiltIn::Satisfy.new(&block)
559
743
  end
744
+ alias_matcher :an_object_satisfying, :satisfy
745
+ alias_matcher :satisfying, :satisfy
560
746
 
561
747
  # Matches if the actual value starts with the expected value(s). In the
562
748
  # case of a string, matches against the first `expected.length` characters
@@ -571,6 +757,9 @@ module RSpec
571
757
  def start_with(*expected)
572
758
  BuiltIn::StartWith.new(*expected)
573
759
  end
760
+ alias_matcher :a_collection_starting_with, :start_with
761
+ alias_matcher :a_string_starting_with, :start_with
762
+ alias_matcher :starting_with, :start_with
574
763
 
575
764
  # Given no argument, matches if a proc throws any Symbol.
576
765
  #
@@ -592,6 +781,14 @@ module RSpec
592
781
  BuiltIn::ThrowSymbol.new(expected_symbol, expected_arg)
593
782
  end
594
783
 
784
+ alias_matcher :a_block_throwing, :throw_symbol do |desc|
785
+ desc.sub("throw", "a block throwing")
786
+ end
787
+
788
+ alias_matcher :throwing, :throw_symbol do |desc|
789
+ desc.sub("throw", "throwing")
790
+ end
791
+
595
792
  # Passes if the method called in the expect block yields, regardless
596
793
  # of whether or not arguments are yielded.
597
794
  #
@@ -607,6 +804,8 @@ module RSpec
607
804
  def yield_control
608
805
  BuiltIn::YieldControl.new
609
806
  end
807
+ alias_matcher :a_block_yielding_control, :yield_control
808
+ alias_matcher :yielding_control, :yield_control
610
809
 
611
810
  # Passes if the method called in the expect block yields with
612
811
  # no arguments. Fails if it does not yield, or yields with arguments.
@@ -624,6 +823,8 @@ module RSpec
624
823
  def yield_with_no_args
625
824
  BuiltIn::YieldWithNoArgs.new
626
825
  end
826
+ alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args
827
+ alias_matcher :yielding_with_no_args, :yield_with_no_args
627
828
 
628
829
  # Given no arguments, matches if the method called in the expect
629
830
  # block yields with arguments (regardless of what they are or how
@@ -653,6 +854,8 @@ module RSpec
653
854
  def yield_with_args(*args)
654
855
  BuiltIn::YieldWithArgs.new(*args)
655
856
  end
857
+ alias_matcher :a_block_yielding_with_args, :yield_with_args
858
+ alias_matcher :yielding_with_args, :yield_with_args
656
859
 
657
860
  # Designed for use with methods that repeatedly yield (such as
658
861
  # iterators). Passes if the method called in the expect block yields
@@ -673,25 +876,47 @@ module RSpec
673
876
  def yield_successive_args(*args)
674
877
  BuiltIn::YieldSuccessiveArgs.new(*args)
675
878
  end
879
+ alias_matcher :a_block_yielding_successive_args, :yield_successive_args
880
+ alias_matcher :yielding_successive_args, :yield_successive_args
881
+
882
+ # Delegates to {RSpec::Expectations.configuration}.
883
+ # This is here because rspec-core's `expect_with` option
884
+ # looks for a `configuration` method on the mixin
885
+ # (`RSpec::Matchers`) to yield to a block.
886
+ # @return [RSpec::Expectations::Configuration] the configuration object
887
+ def self.configuration
888
+ Expectations.configuration
889
+ end
676
890
 
677
- # Passes if actual contains all of the expected regardless of order.
678
- # This works for collections. Pass in multiple args and it will only
679
- # pass if all args are found in collection.
680
- #
681
- # @note This is also available using the `=~` operator with `should`,
682
- # but `=~` is not supported with `expect`.
683
- #
684
- # @note This matcher only supports positive expectations.
685
- # expect(..).not_to match_array(other_array) is not supported.
686
- #
687
- # @example
688
- #
689
- # expect([1,2,3]).to match_array([1,2,3])
690
- # expect([1,2,3]).to match_array([1,3,2])
691
- def match_array(array)
692
- BuiltIn::MatchArray.new(array)
891
+ private
892
+
893
+ BE_PREDICATE_REGEX = /^(be_(?:an?_)?)(.*)/
894
+ HAS_REGEX = /^(?:have_)(.*)/
895
+
896
+ def method_missing(method, *args, &block)
897
+ case method.to_s
898
+ when BE_PREDICATE_REGEX
899
+ BuiltIn::BePredicate.new(method, *args, &block)
900
+ when HAS_REGEX
901
+ BuiltIn::Has.new(method, *args, &block)
902
+ else
903
+ super
904
+ end
905
+ end
906
+
907
+ # @api private
908
+ def self.is_a_matcher?(obj)
909
+ return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj
910
+ return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
911
+ return false unless obj.respond_to?(:matches?)
912
+
913
+ obj.respond_to?(:failure_message) ||
914
+ obj.respond_to?(:failure_message_for_should) # support legacy matchers
693
915
  end
694
916
 
695
- OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
917
+ # @api private
918
+ def self.is_a_describable_matcher?(obj)
919
+ is_a_matcher?(obj) && obj.respond_to?(:description)
920
+ end
696
921
  end
697
922
  end