rspec-expectations 3.0.4 → 3.12.3

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 (59) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +1 -1
  5. data/Changelog.md +530 -5
  6. data/{License.txt → LICENSE.md} +5 -4
  7. data/README.md +73 -31
  8. data/lib/rspec/expectations/block_snippet_extractor.rb +253 -0
  9. data/lib/rspec/expectations/configuration.rb +96 -1
  10. data/lib/rspec/expectations/expectation_target.rb +82 -38
  11. data/lib/rspec/expectations/fail_with.rb +11 -6
  12. data/lib/rspec/expectations/failure_aggregator.rb +229 -0
  13. data/lib/rspec/expectations/handler.rb +36 -15
  14. data/lib/rspec/expectations/minitest_integration.rb +43 -2
  15. data/lib/rspec/expectations/syntax.rb +5 -5
  16. data/lib/rspec/expectations/version.rb +1 -1
  17. data/lib/rspec/expectations.rb +15 -1
  18. data/lib/rspec/matchers/aliased_matcher.rb +79 -4
  19. data/lib/rspec/matchers/built_in/all.rb +11 -0
  20. data/lib/rspec/matchers/built_in/base_matcher.rb +111 -28
  21. data/lib/rspec/matchers/built_in/be.rb +28 -114
  22. data/lib/rspec/matchers/built_in/be_between.rb +1 -1
  23. data/lib/rspec/matchers/built_in/be_instance_of.rb +5 -1
  24. data/lib/rspec/matchers/built_in/be_kind_of.rb +5 -1
  25. data/lib/rspec/matchers/built_in/be_within.rb +5 -12
  26. data/lib/rspec/matchers/built_in/change.rb +171 -63
  27. data/lib/rspec/matchers/built_in/compound.rb +201 -30
  28. data/lib/rspec/matchers/built_in/contain_exactly.rb +73 -12
  29. data/lib/rspec/matchers/built_in/count_expectation.rb +169 -0
  30. data/lib/rspec/matchers/built_in/eq.rb +3 -38
  31. data/lib/rspec/matchers/built_in/eql.rb +2 -2
  32. data/lib/rspec/matchers/built_in/equal.rb +3 -3
  33. data/lib/rspec/matchers/built_in/exist.rb +7 -3
  34. data/lib/rspec/matchers/built_in/has.rb +93 -30
  35. data/lib/rspec/matchers/built_in/have_attributes.rb +114 -0
  36. data/lib/rspec/matchers/built_in/include.rb +133 -25
  37. data/lib/rspec/matchers/built_in/match.rb +79 -2
  38. data/lib/rspec/matchers/built_in/operators.rb +14 -5
  39. data/lib/rspec/matchers/built_in/output.rb +59 -2
  40. data/lib/rspec/matchers/built_in/raise_error.rb +130 -27
  41. data/lib/rspec/matchers/built_in/respond_to.rb +117 -15
  42. data/lib/rspec/matchers/built_in/satisfy.rb +28 -14
  43. data/lib/rspec/matchers/built_in/{start_and_end_with.rb → start_or_end_with.rb} +20 -8
  44. data/lib/rspec/matchers/built_in/throw_symbol.rb +15 -5
  45. data/lib/rspec/matchers/built_in/yield.rb +129 -156
  46. data/lib/rspec/matchers/built_in.rb +5 -3
  47. data/lib/rspec/matchers/composable.rb +24 -36
  48. data/lib/rspec/matchers/dsl.rb +203 -37
  49. data/lib/rspec/matchers/english_phrasing.rb +58 -0
  50. data/lib/rspec/matchers/expecteds_for_multiple_diffs.rb +82 -0
  51. data/lib/rspec/matchers/fail_matchers.rb +42 -0
  52. data/lib/rspec/matchers/generated_descriptions.rb +1 -2
  53. data/lib/rspec/matchers/matcher_delegator.rb +3 -4
  54. data/lib/rspec/matchers/matcher_protocol.rb +105 -0
  55. data/lib/rspec/matchers.rb +267 -144
  56. data.tar.gz.sig +0 -0
  57. metadata +71 -49
  58. metadata.gz.sig +0 -0
  59. data/lib/rspec/matchers/pretty.rb +0 -77
@@ -1,31 +1,24 @@
1
1
  require 'rspec/support'
2
+ RSpec::Support.require_rspec_support 'matcher_definition'
2
3
  RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) }
3
4
 
4
5
  %w[
5
- pretty
6
+ english_phrasing
6
7
  composable
7
8
  built_in
8
9
  generated_descriptions
9
10
  dsl
10
11
  matcher_delegator
11
12
  aliased_matcher
13
+ expecteds_for_multiple_diffs
12
14
  ].each { |file| RSpec::Support.require_rspec_matchers(file) }
13
15
 
14
16
  # RSpec's top level namespace. All of rspec-expectations is contained
15
17
  # in the `RSpec::Expectations` and `RSpec::Matchers` namespaces.
16
18
  module RSpec
17
19
  # RSpec::Matchers provides a number of useful matchers we use to define
18
- # expectations. A matcher is any object that responds to the following:
19
- #
20
- # matches?(actual)
21
- # failure_message
22
- #
23
- # These methods are also part of the matcher protocol, but are optional:
24
- #
25
- # does_not_match?(actual)
26
- # failure_message_when_negated
27
- # description
28
- # supports_block_expectations?
20
+ # expectations. Any object that implements the [matcher protocol](Matchers/MatcherProtocol)
21
+ # can be used as a matcher.
29
22
  #
30
23
  # ## Predicates
31
24
  #
@@ -43,14 +36,14 @@ module RSpec
43
36
  # expect([]).to be_empty # => [].empty?() | passes
44
37
  # expect([]).not_to be_empty # => [].empty?() | fails
45
38
  #
46
- # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_"
39
+ # In addition to prefixing the predicate matchers with "be_", you can also use "be_a_"
47
40
  # and "be_an_", making your specs read much more naturally:
48
41
  #
49
42
  # expect("a string").to be_an_instance_of(String) # =>"a string".instance_of?(String) # passes
50
43
  #
51
- # expect(3).to be_a_kind_of(Fixnum) # => 3.kind_of?(Numeric) | passes
52
- # expect(3).to be_a_kind_of(Numeric) # => 3.kind_of?(Numeric) | passes
53
- # expect(3).to be_an_instance_of(Fixnum) # => 3.instance_of?(Fixnum) | passes
44
+ # expect(3).to be_a_kind_of(Integer) # => 3.kind_of?(Numeric) | passes
45
+ # expect(3).to be_a_kind_of(Numeric) # => 3.kind_of?(Numeric) | passes
46
+ # expect(3).to be_an_instance_of(Integer) # => 3.instance_of?(Integer) | passes
54
47
  # expect(3).not_to be_an_instance_of(Numeric) # => 3.instance_of?(Numeric) | fails
55
48
  #
56
49
  # RSpec will also create custom matchers for predicates like `has_key?`. To
@@ -69,6 +62,26 @@ module RSpec
69
62
  # RSpec::Matchers.alias_matcher :a_user_who_is_an_admin, :be_an_admin
70
63
  # expect(user_list).to include(a_user_who_is_an_admin)
71
64
  #
65
+ # ## Alias Matchers
66
+ #
67
+ # With {RSpec::Matchers.alias_matcher}, you can easily create an
68
+ # alternate name for a given matcher.
69
+ #
70
+ # The description will also change according to the new name:
71
+ #
72
+ # RSpec::Matchers.alias_matcher :a_list_that_sums_to, :sum_to
73
+ # sum_to(3).description # => "sum to 3"
74
+ # a_list_that_sums_to(3).description # => "a list that sums to 3"
75
+ #
76
+ # or you can specify a custom description like this:
77
+ #
78
+ # RSpec::Matchers.alias_matcher :a_list_sorted_by, :be_sorted_by do |description|
79
+ # description.sub("be sorted by", "a list sorted by")
80
+ # end
81
+ #
82
+ # be_sorted_by(:age).description # => "be sorted by age"
83
+ # a_list_sorted_by(:age).description # => "a list sorted by age"
84
+ #
72
85
  # ## Custom Matchers
73
86
  #
74
87
  # When you find that none of the stock matchers provide a natural feeling
@@ -209,55 +222,88 @@ module RSpec
209
222
  # expressions, and also uses the noun-phrase wording in the matcher's `description`,
210
223
  # for readable failure messages. You can alias your custom matchers in similar fashion
211
224
  # using {RSpec::Matchers.alias_matcher}.
212
- module Matchers
225
+ #
226
+ # ## Negated Matchers
227
+ #
228
+ # Sometimes if you want to test for the opposite using a more descriptive name
229
+ # instead of using `not_to`, you can use {RSpec::Matchers.define_negated_matcher}:
230
+ #
231
+ # RSpec::Matchers.define_negated_matcher :exclude, :include
232
+ # include(1, 2).description # => "include 1 and 2"
233
+ # exclude(1, 2).description # => "exclude 1 and 2"
234
+ #
235
+ # While the most obvious negated form may be to add a `not_` prefix,
236
+ # the failure messages you get with that form can be confusing (e.g.
237
+ # "expected [actual] to not [verb], but did not"). We've found it works
238
+ # best to find a more positive name for the negated form, such as
239
+ # `avoid_changing` rather than `not_change`.
240
+ #
241
+ module Matchers # rubocop:disable Metrics/ModuleLength
242
+ extend ::RSpec::Matchers::DSL
243
+
244
+ # @!macro [attach] alias_matcher
245
+ # @!parse
246
+ # alias $1 $2
247
+ # @!visibility private
248
+ # We define this override here so we can attach a YARD macro to it.
249
+ # It ensures that our docs list all the matcher aliases.
250
+ def self.alias_matcher(*args, &block)
251
+ super(*args, &block)
252
+ end
253
+
254
+ # @!method self.alias_matcher(new_name, old_name, options={}, &description_override)
255
+ # Extended from {RSpec::Matchers::DSL#alias_matcher}.
256
+
257
+ # @!method self.define(name, &declarations)
258
+ # Extended from {RSpec::Matchers::DSL#define}.
259
+
260
+ # @!method self.define_negated_matcher(negated_name, base_name, &description_override)
261
+ # Extended from {RSpec::Matchers::DSL#define_negated_matcher}.
262
+
213
263
  # @method expect
214
264
  # Supports `expect(actual).to matcher` syntax by wrapping `actual` in an
215
265
  # `ExpectationTarget`.
216
266
  # @example
217
267
  # expect(actual).to eq(expected)
218
268
  # expect(actual).not_to eq(expected)
219
- # @return [ExpectationTarget]
220
- # @see ExpectationTarget#to
221
- # @see ExpectationTarget#not_to
269
+ # @return [Expectations::ExpectationTarget]
270
+ # @see Expectations::ExpectationTarget#to
271
+ # @see Expectations::ExpectationTarget#not_to
222
272
 
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"
273
+ # Allows multiple expectations in the provided block to fail, and then
274
+ # aggregates them into a single exception, rather than aborting on the
275
+ # first expectation failure like normal. This allows you to see all
276
+ # failures from an entire set of expectations without splitting each
277
+ # off into its own example (which may slow things down if the example
278
+ # setup is expensive).
279
+ #
280
+ # @param label [String] label for this aggregation block, which will be
281
+ # included in the aggregated exception message.
282
+ # @param metadata [Hash] additional metadata about this failure aggregation
283
+ # block. If multiple expectations fail, it will be exposed from the
284
+ # {Expectations::MultipleExpectationsNotMetError} exception. Mostly
285
+ # intended for internal RSpec use but you can use it as well.
286
+ # @yield Block containing as many expectation as you want. The block is
287
+ # simply yielded to, so you can trust that anything that works outside
288
+ # the block should work within it.
289
+ # @raise [Expectations::MultipleExpectationsNotMetError] raised when
290
+ # multiple expectations fail.
291
+ # @raise [Expectations::ExpectationNotMetError] raised when a single
292
+ # expectation fails.
293
+ # @raise [Exception] other sorts of exceptions will be raised as normal.
239
294
  #
240
295
  # @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")
296
+ # aggregate_failures("verifying response") do
297
+ # expect(response.status).to eq(200)
298
+ # expect(response.headers).to include("Content-Type" => "text/plain")
299
+ # expect(response.body).to include("Success")
244
300
  # end
245
301
  #
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
302
+ # @note The implementation of this feature uses a thread-local variable,
303
+ # which means that if you have an expectation failure in another thread,
304
+ # it'll abort like normal.
305
+ def aggregate_failures(label=nil, metadata={}, &block)
306
+ Expectations::FailureAggregator.new(label, metadata).aggregate(&block)
261
307
  end
262
308
 
263
309
  # Passes if actual is truthy (anything but false or nil)
@@ -270,9 +316,9 @@ module RSpec
270
316
  def be_falsey
271
317
  BuiltIn::BeFalsey.new
272
318
  end
273
- alias_matcher :be_falsy, :be_falsey
319
+ alias_matcher :be_falsy, :be_falsey
274
320
  alias_matcher :a_falsey_value, :be_falsey
275
- alias_matcher :a_falsy_value, :be_falsey
321
+ alias_matcher :a_falsy_value, :be_falsey
276
322
 
277
323
  # Passes if actual is nil
278
324
  def be_nil
@@ -303,7 +349,7 @@ module RSpec
303
349
  def be(*args)
304
350
  args.empty? ? Matchers::BuiltIn::Be.new : equal(*args)
305
351
  end
306
- alias_matcher :a_value, :be
352
+ alias_matcher :a_value, :be, :klass => AliasedMatcherWithOperatorSupport
307
353
 
308
354
  # passes if target.kind_of?(klass)
309
355
  def be_a(klass)
@@ -314,8 +360,7 @@ module RSpec
314
360
  # Passes if actual.instance_of?(expected)
315
361
  #
316
362
  # @example
317
- #
318
- # expect(5).to be_an_instance_of(Fixnum)
363
+ # expect(5).to be_an_instance_of(Integer)
319
364
  # expect(5).not_to be_an_instance_of(Numeric)
320
365
  # expect(5).not_to be_an_instance_of(Float)
321
366
  def be_an_instance_of(expected)
@@ -327,15 +372,14 @@ module RSpec
327
372
  # Passes if actual.kind_of?(expected)
328
373
  #
329
374
  # @example
330
- #
331
- # expect(5).to be_a_kind_of(Fixnum)
375
+ # expect(5).to be_a_kind_of(Integer)
332
376
  # expect(5).to be_a_kind_of(Numeric)
333
377
  # expect(5).not_to be_a_kind_of(Float)
334
378
  def be_a_kind_of(expected)
335
379
  BuiltIn::BeAKindOf.new(expected)
336
380
  end
337
381
  alias_method :be_kind_of, :be_a_kind_of
338
- alias_matcher :a_kind_of, :be_a_kind_of
382
+ alias_matcher :a_kind_of, :be_a_kind_of
339
383
 
340
384
  # Passes if actual.between?(min, max). Works with any Comparable object,
341
385
  # including String, Symbol, Time, or Numeric (Fixnum, Bignum, Integer,
@@ -345,7 +389,6 @@ module RSpec
345
389
  # but you can make it `exclusive` by chaining that off the matcher.
346
390
  #
347
391
  # @example
348
- #
349
392
  # expect(5).to be_between(1, 10)
350
393
  # expect(11).not_to be_between(1, 10)
351
394
  # expect(10).not_to be_between(1, 10).exclusive
@@ -357,14 +400,13 @@ module RSpec
357
400
  # Passes if actual == expected +/- delta
358
401
  #
359
402
  # @example
360
- #
361
403
  # expect(result).to be_within(0.5).of(3.0)
362
404
  # expect(result).not_to be_within(0.5).of(3.0)
363
405
  def be_within(delta)
364
406
  BuiltIn::BeWithin.new(delta)
365
407
  end
366
408
  alias_matcher :a_value_within, :be_within
367
- alias_matcher :within, :be_within
409
+ alias_matcher :within, :be_within
368
410
 
369
411
  # Applied to a proc, specifies that its execution will cause some value to
370
412
  # change.
@@ -382,14 +424,16 @@ module RSpec
382
424
  # You can chain any of the following off of the end to specify details
383
425
  # about the change:
384
426
  #
427
+ # * `from`
428
+ # * `to`
429
+ #
430
+ # or any one of:
431
+ #
385
432
  # * `by`
386
433
  # * `by_at_least`
387
434
  # * `by_at_most`
388
- # * `from`
389
- # * `to`
390
435
  #
391
436
  # @example
392
- #
393
437
  # expect {
394
438
  # team.add_player(player)
395
439
  # }.to change(roster, :count)
@@ -436,7 +480,10 @@ module RSpec
436
480
  # == Notes
437
481
  #
438
482
  # Evaluates `receiver.message` or `block` before and after it
439
- # evaluates the block passed to `expect`.
483
+ # evaluates the block passed to `expect`. If the value is the same
484
+ # object, its before/after `hash` value is used to see if it has changed.
485
+ # Therefore, your object needs to properly implement `hash` to work correctly
486
+ # with this matcher.
440
487
  #
441
488
  # `expect( ... ).not_to change` supports the form that specifies `from`
442
489
  # (which specifies what you expect the starting, unchanged value to be)
@@ -445,8 +492,8 @@ module RSpec
445
492
  def change(receiver=nil, message=nil, &block)
446
493
  BuiltIn::Change.new(receiver, message, &block)
447
494
  end
448
- alias_matcher :a_block_changing, :change
449
- alias_matcher :changing, :change
495
+ alias_matcher :a_block_changing, :change
496
+ alias_matcher :changing, :change
450
497
 
451
498
  # Passes if actual contains all of the expected regardless of order.
452
499
  # This works for collections. Pass in multiple args and it will only
@@ -455,11 +502,7 @@ module RSpec
455
502
  # @note This is also available using the `=~` operator with `should`,
456
503
  # but `=~` is not supported with `expect`.
457
504
  #
458
- # @note This matcher only supports positive expectations.
459
- # `expect(...).not_to contain_exactly(other_array)` is not supported.
460
- #
461
505
  # @example
462
- #
463
506
  # expect([1, 2, 3]).to contain_exactly(1, 2, 3)
464
507
  # expect([1, 2, 3]).to contain_exactly(1, 3, 2)
465
508
  #
@@ -468,7 +511,7 @@ module RSpec
468
511
  BuiltIn::ContainExactly.new(items)
469
512
  end
470
513
  alias_matcher :a_collection_containing_exactly, :contain_exactly
471
- alias_matcher :containing_exactly, :contain_exactly
514
+ alias_matcher :containing_exactly, :contain_exactly
472
515
 
473
516
  # Passes if actual covers expected. This works for
474
517
  # Ranges. You can also pass in multiple args
@@ -486,7 +529,7 @@ module RSpec
486
529
  BuiltIn::Cover.new(*values)
487
530
  end
488
531
  alias_matcher :a_range_covering, :cover
489
- alias_matcher :covering, :cover
532
+ alias_matcher :covering, :cover
490
533
 
491
534
  # Matches if the actual value ends with the expected value(s). In the case
492
535
  # of a string, matches against the last `expected.length` characters of the
@@ -494,7 +537,6 @@ module RSpec
494
537
  # `expected.length` elements of the actual array.
495
538
  #
496
539
  # @example
497
- #
498
540
  # expect("this string").to end_with "string"
499
541
  # expect([0, 1, 2, 3, 4]).to end_with 4
500
542
  # expect([0, 2, 3, 4, 4]).to end_with 3, 4
@@ -502,8 +544,8 @@ module RSpec
502
544
  BuiltIn::EndWith.new(*expected)
503
545
  end
504
546
  alias_matcher :a_collection_ending_with, :end_with
505
- alias_matcher :a_string_ending_with, :end_with
506
- alias_matcher :ending_with, :end_with
547
+ alias_matcher :a_string_ending_with, :end_with
548
+ alias_matcher :ending_with, :end_with
507
549
 
508
550
  # Passes if <tt>actual == expected</tt>.
509
551
  #
@@ -511,14 +553,13 @@ module RSpec
511
553
  # information about equality in Ruby.
512
554
  #
513
555
  # @example
514
- #
515
556
  # expect(5).to eq(5)
516
557
  # expect(5).not_to eq(3)
517
558
  def eq(expected)
518
559
  BuiltIn::Eq.new(expected)
519
560
  end
520
561
  alias_matcher :an_object_eq_to, :eq
521
- alias_matcher :eq_to, :eq
562
+ alias_matcher :eq_to, :eq
522
563
 
523
564
  # Passes if `actual.eql?(expected)`
524
565
  #
@@ -526,14 +567,13 @@ module RSpec
526
567
  # information about equality in Ruby.
527
568
  #
528
569
  # @example
529
- #
530
570
  # expect(5).to eql(5)
531
571
  # expect(5).not_to eql(3)
532
572
  def eql(expected)
533
573
  BuiltIn::Eql.new(expected)
534
574
  end
535
575
  alias_matcher :an_object_eql_to, :eql
536
- alias_matcher :eql_to, :eql
576
+ alias_matcher :eql_to, :eql
537
577
 
538
578
  # Passes if <tt>actual.equal?(expected)</tt> (object identity).
539
579
  #
@@ -541,14 +581,13 @@ module RSpec
541
581
  # information about equality in Ruby.
542
582
  #
543
583
  # @example
544
- #
545
- # expect(5).to equal(5) # Fixnums are equal
584
+ # expect(5).to equal(5) # Integers are equal
546
585
  # expect("5").not_to equal("5") # Strings that look the same are not the same object
547
586
  def equal(expected)
548
587
  BuiltIn::Equal.new(expected)
549
588
  end
550
589
  alias_matcher :an_object_equal_to, :equal
551
- alias_matcher :equal_to, :equal
590
+ alias_matcher :equal_to, :equal
552
591
 
553
592
  # Passes if `actual.exist?` or `actual.exists?`
554
593
  #
@@ -558,33 +597,57 @@ module RSpec
558
597
  BuiltIn::Exist.new(*args)
559
598
  end
560
599
  alias_matcher :an_object_existing, :exist
561
- alias_matcher :existing, :exist
600
+ alias_matcher :existing, :exist
601
+
602
+ # Passes if actual's attribute values match the expected attributes hash.
603
+ # This works no matter how you define your attribute readers.
604
+ #
605
+ # @example
606
+ # Person = Struct.new(:name, :age)
607
+ # person = Person.new("Bob", 32)
608
+ #
609
+ # expect(person).to have_attributes(:name => "Bob", :age => 32)
610
+ # expect(person).to have_attributes(:name => a_string_starting_with("B"), :age => (a_value > 30) )
611
+ #
612
+ # @note It will fail if actual doesn't respond to any of the expected attributes.
613
+ #
614
+ # @example
615
+ # expect(person).to have_attributes(:color => "red")
616
+ def have_attributes(expected)
617
+ BuiltIn::HaveAttributes.new(expected)
618
+ end
619
+ alias_matcher :an_object_having_attributes, :have_attributes
620
+ alias_matcher :having_attributes, :have_attributes
562
621
 
563
622
  # Passes if actual includes expected. This works for
564
623
  # collections and Strings. You can also pass in multiple args
565
624
  # and it will only pass if all args are found in collection.
566
625
  #
567
626
  # @example
568
- #
569
627
  # expect([1,2,3]).to include(3)
570
628
  # expect([1,2,3]).to include(2,3)
571
629
  # expect([1,2,3]).to include(2,3,4) # fails
572
630
  # expect([1,2,3]).not_to include(4)
573
631
  # expect("spread").to include("read")
574
632
  # expect("spread").not_to include("red")
633
+ # expect(:a => 1, :b => 2).to include(:a)
634
+ # expect(:a => 1, :b => 2).to include(:a, :b)
635
+ # expect(:a => 1, :b => 2).to include(:a => 1)
636
+ # expect(:a => 1, :b => 2).to include(:b => 2, :a => 1)
637
+ # expect(:a => 1, :b => 2).to include(:c) # fails
638
+ # expect(:a => 1, :b => 2).not_to include(:a => 2)
575
639
  def include(*expected)
576
640
  BuiltIn::Include.new(*expected)
577
641
  end
578
642
  alias_matcher :a_collection_including, :include
579
- alias_matcher :a_string_including, :include
580
- alias_matcher :a_hash_including, :include
581
- alias_matcher :including, :include
643
+ alias_matcher :a_string_including, :include
644
+ alias_matcher :a_hash_including, :include
645
+ alias_matcher :including, :include
582
646
 
583
- # Passes if actual all expected objects pass. This works for
584
- # any enumerable object.
647
+ # Passes if the provided matcher passes when checked against all
648
+ # elements of the collection.
585
649
  #
586
650
  # @example
587
- #
588
651
  # expect([1, 3, 5]).to all be_odd
589
652
  # expect([1, 3, 6]).to all be_odd # fails
590
653
  #
@@ -606,12 +669,10 @@ module RSpec
606
669
  # pair of elements.
607
670
  #
608
671
  # @example
609
- #
610
672
  # expect(email).to match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
611
673
  # expect(email).to match("@example.com")
612
674
  #
613
675
  # @example
614
- #
615
676
  # hash = {
616
677
  # :a => {
617
678
  # :b => ["foo", 5],
@@ -623,7 +684,7 @@ module RSpec
623
684
  # :a => {
624
685
  # :b => a_collection_containing_exactly(
625
686
  # a_string_starting_with("f"),
626
- # an_instance_of(Fixnum)
687
+ # an_instance_of(Integer)
627
688
  # ),
628
689
  # :c => { :d => (a_value < 3) }
629
690
  # }
@@ -636,17 +697,16 @@ module RSpec
636
697
  def match(expected)
637
698
  BuiltIn::Match.new(expected)
638
699
  end
639
- alias_matcher :match_regex, :match
700
+ alias_matcher :match_regex, :match
640
701
  alias_matcher :an_object_matching, :match
641
- alias_matcher :a_string_matching, :match
642
- alias_matcher :matching, :match
702
+ alias_matcher :a_string_matching, :match
703
+ alias_matcher :matching, :match
643
704
 
644
705
  # An alternate form of `contain_exactly` that accepts
645
706
  # the expected contents as a single array arg rather
646
- # that splatted out as individual items.
707
+ # than splatted out as individual items.
647
708
  #
648
709
  # @example
649
- #
650
710
  # expect(results).to contain_exactly(1, 2)
651
711
  # # is identical to:
652
712
  # expect(results).to match_array([1, 2])
@@ -655,13 +715,19 @@ module RSpec
655
715
  def match_array(items)
656
716
  contain_exactly(*items)
657
717
  end
718
+ alias_matcher :an_array_matching, :match_array do |desc|
719
+ desc.sub("contain exactly", "an array containing exactly")
720
+ end
658
721
 
659
722
  # With no arg, passes if the block outputs `to_stdout` or `to_stderr`.
660
- # With a string, passes if the blocks outputs that specific string `to_stdout` or `to_stderr`.
661
- # With a regexp or matcher, passes if the blocks outputs a string `to_stdout` or `to_stderr` that matches.
723
+ # With a string, passes if the block outputs that specific string `to_stdout` or `to_stderr`.
724
+ # With a regexp or matcher, passes if the block outputs a string `to_stdout` or `to_stderr` that matches.
662
725
  #
663
- # @example
726
+ # To capture output from any spawned subprocess as well, use `to_stdout_from_any_process` or
727
+ # `to_stderr_from_any_process`. Output from any process that inherits the main process's corresponding
728
+ # standard stream will be captured.
664
729
  #
730
+ # @example
665
731
  # expect { print 'foo' }.to output.to_stdout
666
732
  # expect { print 'foo' }.to output('foo').to_stdout
667
733
  # expect { print 'foo' }.to output(/foo/).to_stdout
@@ -674,10 +740,15 @@ module RSpec
674
740
  #
675
741
  # expect { do_something }.to_not output.to_stderr
676
742
  #
677
- # @note This matcher works by temporarily replacing `$stdout` or `$stderr`,
678
- # so it's not able to intercept stream output that explicitly uses `STDOUT`/`STDERR`
743
+ # expect { system('echo foo') }.to output("foo\n").to_stdout_from_any_process
744
+ # expect { system('echo foo', out: :err) }.to output("foo\n").to_stderr_from_any_process
745
+ #
746
+ # @note `to_stdout` and `to_stderr` work by temporarily replacing `$stdout` or `$stderr`,
747
+ # so they're not able to intercept stream output that explicitly uses `STDOUT`/`STDERR`
679
748
  # or that uses a reference to `$stdout`/`$stderr` that was stored before the
680
- # matcher is used.
749
+ # matcher was used.
750
+ # @note `to_stdout_from_any_process` and `to_stderr_from_any_process` use Tempfiles, and
751
+ # are thus significantly (~30x) slower than `to_stdout` and `to_stderr`.
681
752
  def output(expected=nil)
682
753
  BuiltIn::Output.new(expected)
683
754
  end
@@ -685,29 +756,30 @@ module RSpec
685
756
 
686
757
  # With no args, matches if any error is raised.
687
758
  # With a named error, matches only if that specific error is raised.
688
- # With a named error and messsage specified as a String, matches only if both match.
689
- # With a named error and messsage specified as a Regexp, matches only if both match.
759
+ # With a named error and message specified as a String, matches only if both match.
760
+ # With a named error and message specified as a Regexp, matches only if both match.
690
761
  # Pass an optional block to perform extra verifications on the exception matched
691
762
  #
692
763
  # @example
693
- #
694
764
  # expect { do_something_risky }.to raise_error
695
765
  # expect { do_something_risky }.to raise_error(PoorRiskDecisionError)
696
766
  # expect { do_something_risky }.to raise_error(PoorRiskDecisionError) { |error| expect(error.data).to eq 42 }
767
+ # expect { do_something_risky }.to raise_error { |error| expect(error.data).to eq 42 }
697
768
  # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, "that was too risky")
698
769
  # expect { do_something_risky }.to raise_error(PoorRiskDecisionError, /oo ri/)
770
+ # expect { do_something_risky }.to raise_error("that was too risky")
699
771
  #
700
772
  # expect { do_something_risky }.not_to raise_error
701
- def raise_error(error=Exception, message=nil, &block)
773
+ def raise_error(error=BuiltIn::RaiseError::UndefinedValue, message=nil, &block)
702
774
  BuiltIn::RaiseError.new(error, message, &block)
703
775
  end
704
- alias_method :raise_exception, :raise_error
776
+ alias_method :raise_exception, :raise_error
705
777
 
706
- alias_matcher :a_block_raising, :raise_error do |desc|
778
+ alias_matcher :a_block_raising, :raise_error do |desc|
707
779
  desc.sub("raise", "a block raising")
708
780
  end
709
781
 
710
- alias_matcher :raising, :raise_error do |desc|
782
+ alias_matcher :raising, :raise_error do |desc|
711
783
  desc.sub("raise", "raising")
712
784
  end
713
785
 
@@ -715,14 +787,13 @@ module RSpec
715
787
  # provided. Names can be Strings or Symbols.
716
788
  #
717
789
  # @example
718
- #
719
790
  # expect("string").to respond_to(:length)
720
791
  #
721
792
  def respond_to(*names)
722
793
  BuiltIn::RespondTo.new(*names)
723
794
  end
724
795
  alias_matcher :an_object_responding_to, :respond_to
725
- alias_matcher :responding_to, :respond_to
796
+ alias_matcher :responding_to, :respond_to
726
797
 
727
798
  # Passes if the submitted block returns true. Yields target to the
728
799
  # block.
@@ -734,14 +805,16 @@ module RSpec
734
805
  # If you do find yourself in such a situation, you could always write
735
806
  # a custom matcher, which would likely make your specs more expressive.
736
807
  #
737
- # @example
808
+ # @param description [String] optional description to be used for this matcher.
738
809
  #
810
+ # @example
739
811
  # expect(5).to satisfy { |n| n > 3 }
740
- def satisfy(&block)
741
- BuiltIn::Satisfy.new(&block)
812
+ # expect(5).to satisfy("be greater than 3") { |n| n > 3 }
813
+ def satisfy(description=nil, &block)
814
+ BuiltIn::Satisfy.new(description, &block)
742
815
  end
743
816
  alias_matcher :an_object_satisfying, :satisfy
744
- alias_matcher :satisfying, :satisfy
817
+ alias_matcher :satisfying, :satisfy
745
818
 
746
819
  # Matches if the actual value starts with the expected value(s). In the
747
820
  # case of a string, matches against the first `expected.length` characters
@@ -749,7 +822,6 @@ module RSpec
749
822
  # `expected.length` elements of the actual array.
750
823
  #
751
824
  # @example
752
- #
753
825
  # expect("this string").to start_with "this s"
754
826
  # expect([0, 1, 2, 3, 4]).to start_with 0
755
827
  # expect([0, 2, 3, 4, 4]).to start_with 0, 1
@@ -757,8 +829,8 @@ module RSpec
757
829
  BuiltIn::StartWith.new(*expected)
758
830
  end
759
831
  alias_matcher :a_collection_starting_with, :start_with
760
- alias_matcher :a_string_starting_with, :start_with
761
- alias_matcher :starting_with, :start_with
832
+ alias_matcher :a_string_starting_with, :start_with
833
+ alias_matcher :starting_with, :start_with
762
834
 
763
835
  # Given no argument, matches if a proc throws any Symbol.
764
836
  #
@@ -768,7 +840,6 @@ module RSpec
768
840
  # specified Symbol with the specified arg.
769
841
  #
770
842
  # @example
771
- #
772
843
  # expect { do_something_risky }.to throw_symbol
773
844
  # expect { do_something_risky }.to throw_symbol(:that_was_risky)
774
845
  # expect { do_something_risky }.to throw_symbol(:that_was_risky, 'culprit')
@@ -784,7 +855,7 @@ module RSpec
784
855
  desc.sub("throw", "a block throwing")
785
856
  end
786
857
 
787
- alias_matcher :throwing, :throw_symbol do |desc|
858
+ alias_matcher :throwing, :throw_symbol do |desc|
788
859
  desc.sub("throw", "throwing")
789
860
  end
790
861
 
@@ -792,25 +863,21 @@ module RSpec
792
863
  # of whether or not arguments are yielded.
793
864
  #
794
865
  # @example
795
- #
796
866
  # expect { |b| 5.tap(&b) }.to yield_control
797
867
  # expect { |b| "a".to_sym(&b) }.not_to yield_control
798
868
  #
799
869
  # @note Your expect block must accept a parameter and pass it on to
800
870
  # the method-under-test as a block.
801
- # @note This matcher is not designed for use with methods that yield
802
- # multiple times.
803
871
  def yield_control
804
872
  BuiltIn::YieldControl.new
805
873
  end
806
- alias_matcher :a_block_yielding_control, :yield_control
807
- alias_matcher :yielding_control, :yield_control
874
+ alias_matcher :a_block_yielding_control, :yield_control
875
+ alias_matcher :yielding_control, :yield_control
808
876
 
809
877
  # Passes if the method called in the expect block yields with
810
878
  # no arguments. Fails if it does not yield, or yields with arguments.
811
879
  #
812
880
  # @example
813
- #
814
881
  # expect { |b| User.transaction(&b) }.to yield_with_no_args
815
882
  # expect { |b| 5.tap(&b) }.not_to yield_with_no_args # because it yields with `5`
816
883
  # expect { |b| "a".to_sym(&b) }.not_to yield_with_no_args # because it does not yield
@@ -822,8 +889,8 @@ module RSpec
822
889
  def yield_with_no_args
823
890
  BuiltIn::YieldWithNoArgs.new
824
891
  end
825
- alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args
826
- alias_matcher :yielding_with_no_args, :yield_with_no_args
892
+ alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args
893
+ alias_matcher :yielding_with_no_args, :yield_with_no_args
827
894
 
828
895
  # Given no arguments, matches if the method called in the expect
829
896
  # block yields with arguments (regardless of what they are or how
@@ -837,10 +904,9 @@ module RSpec
837
904
  # operator, the matcher will pass.
838
905
  #
839
906
  # @example
840
- #
841
907
  # expect { |b| 5.tap(&b) }.to yield_with_args # because #tap yields an arg
842
908
  # expect { |b| 5.tap(&b) }.to yield_with_args(5) # because 5 == 5
843
- # expect { |b| 5.tap(&b) }.to yield_with_args(Fixnum) # because Fixnum === 5
909
+ # expect { |b| 5.tap(&b) }.to yield_with_args(Integer) # because Integer === 5
844
910
  # expect { |b| File.open("f.txt", &b) }.to yield_with_args(/txt/) # because /txt/ === "f.txt"
845
911
  #
846
912
  # expect { |b| User.transaction(&b) }.not_to yield_with_args # because it yields no args
@@ -853,8 +919,8 @@ module RSpec
853
919
  def yield_with_args(*args)
854
920
  BuiltIn::YieldWithArgs.new(*args)
855
921
  end
856
- alias_matcher :a_block_yielding_with_args, :yield_with_args
857
- alias_matcher :yielding_with_args, :yield_with_args
922
+ alias_matcher :a_block_yielding_with_args, :yield_with_args
923
+ alias_matcher :yielding_with_args, :yield_with_args
858
924
 
859
925
  # Designed for use with methods that repeatedly yield (such as
860
926
  # iterators). Passes if the method called in the expect block yields
@@ -865,7 +931,6 @@ module RSpec
865
931
  # operator, the matcher will pass.
866
932
  #
867
933
  # @example
868
- #
869
934
  # expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3)
870
935
  # expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2])
871
936
  # expect { |b| [1, 2, 3].each(&b) }.not_to yield_successive_args(1, 2)
@@ -875,8 +940,8 @@ module RSpec
875
940
  def yield_successive_args(*args)
876
941
  BuiltIn::YieldSuccessiveArgs.new(*args)
877
942
  end
878
- alias_matcher :a_block_yielding_successive_args, :yield_successive_args
879
- alias_matcher :yielding_successive_args, :yield_successive_args
943
+ alias_matcher :a_block_yielding_successive_args, :yield_successive_args
944
+ alias_matcher :yielding_successive_args, :yield_successive_args
880
945
 
881
946
  # Delegates to {RSpec::Expectations.configuration}.
882
947
  # This is here because rspec-core's `expect_with` option
@@ -889,8 +954,9 @@ module RSpec
889
954
 
890
955
  private
891
956
 
892
- BE_PREDICATE_REGEX = /^(be_(?:an?_)?)(.*)/
957
+ BE_PREDICATE_REGEX = /^(?:be_(?:an?_)?)(.*)/
893
958
  HAS_REGEX = /^(?:have_)(.*)/
959
+ DYNAMIC_MATCHER_REGEX = Regexp.union(BE_PREDICATE_REGEX, HAS_REGEX)
894
960
 
895
961
  def method_missing(method, *args, &block)
896
962
  case method.to_s
@@ -902,20 +968,77 @@ module RSpec
902
968
  super
903
969
  end
904
970
  end
971
+ ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
972
+
973
+ if RUBY_VERSION.to_f >= 1.9
974
+ def respond_to_missing?(method, *)
975
+ method =~ DYNAMIC_MATCHER_REGEX || super
976
+ end
977
+ else # for 1.8.7
978
+ # :nocov:
979
+ def respond_to?(method, *)
980
+ method = method.to_s
981
+ method =~ DYNAMIC_MATCHER_REGEX || super
982
+ end
983
+ public :respond_to?
984
+ # :nocov:
985
+ end
905
986
 
906
987
  # @api private
907
988
  def self.is_a_matcher?(obj)
908
989
  return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj
909
- return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
990
+ begin
991
+ return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
992
+ rescue NoMethodError
993
+ # Some objects, like BasicObject, don't implemented standard
994
+ # reflection methods.
995
+ return false
996
+ end
910
997
  return false unless obj.respond_to?(:matches?)
911
998
 
912
999
  obj.respond_to?(:failure_message) ||
913
1000
  obj.respond_to?(:failure_message_for_should) # support legacy matchers
914
1001
  end
915
1002
 
1003
+ ::RSpec::Support.register_matcher_definition do |obj|
1004
+ is_a_matcher?(obj)
1005
+ end
1006
+
916
1007
  # @api private
917
1008
  def self.is_a_describable_matcher?(obj)
918
1009
  is_a_matcher?(obj) && obj.respond_to?(:description)
919
1010
  end
1011
+
1012
+ class << self
1013
+ private
1014
+
1015
+ if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9'
1016
+ # Note that `included` doesn't work for this because it is triggered
1017
+ # _after_ `RSpec::Matchers` is an ancestor of the inclusion host, rather
1018
+ # than _before_, like `append_features`. It's important we check this before
1019
+ # in order to find the cases where it was already previously included.
1020
+ # @api private
1021
+ def append_features(mod)
1022
+ return super if mod < self # `mod < self` indicates a re-inclusion.
1023
+
1024
+ subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self }
1025
+ return super unless subclasses.any?
1026
+
1027
+ subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor.
1028
+ subclasses = subclasses.map { |s| "`#{s}`" }.join(", ")
1029
+
1030
+ RSpec.warning "`#{self}` has been included in a superclass (`#{mod}`) " \
1031
+ "after previously being included in subclasses (#{subclasses}), " \
1032
+ "which can trigger infinite recursion from `super` due to an MRI 1.9 bug " \
1033
+ "(https://redmine.ruby-lang.org/issues/3351). To work around this, " \
1034
+ "either upgrade to MRI 2.0+, include a dup of the module (e.g. " \
1035
+ "`include #{self}.dup`), or find a way to include `#{self}` in `#{mod}` " \
1036
+ "before it is included in subclasses (#{subclasses}). See " \
1037
+ "https://github.com/rspec/rspec-expectations/issues/814 for more info"
1038
+
1039
+ super
1040
+ end
1041
+ end
1042
+ end
920
1043
  end
921
1044
  end