rspec-expectations 2.14.5 → 2.99.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 (63) hide show
  1. checksums.yaml +15 -7
  2. data/Changelog.md +114 -31
  3. data/features/README.md +2 -1
  4. data/features/built_in_matchers/be.feature +40 -40
  5. data/features/step_definitions/additional_cli_steps.rb +10 -0
  6. data/features/test_frameworks/test_unit.feature +40 -0
  7. data/lib/rspec/expectations/caller_filter.rb +60 -0
  8. data/lib/rspec/{matchers → expectations}/configuration.rb +5 -3
  9. data/lib/rspec/expectations/deprecation.rb +11 -15
  10. data/lib/rspec/expectations/expectation_target.rb +75 -8
  11. data/lib/rspec/expectations/handler.rb +5 -1
  12. data/lib/rspec/expectations/syntax.rb +3 -5
  13. data/lib/rspec/expectations/version.rb +1 -2
  14. data/lib/rspec/expectations.rb +1 -1
  15. data/lib/rspec/matchers/be_close.rb +4 -1
  16. data/lib/rspec/matchers/built_in/base_matcher.rb +10 -5
  17. data/lib/rspec/matchers/built_in/be.rb +38 -9
  18. data/lib/rspec/matchers/built_in/be_within.rb +8 -2
  19. data/lib/rspec/matchers/built_in/change.rb +39 -1
  20. data/lib/rspec/matchers/built_in/has.rb +40 -7
  21. data/lib/rspec/matchers/built_in/have.rb +151 -2
  22. data/lib/rspec/matchers/built_in/include.rb +1 -1
  23. data/lib/rspec/matchers/built_in/match_array.rb +1 -1
  24. data/lib/rspec/matchers/built_in/raise_error.rb +7 -1
  25. data/lib/rspec/matchers/built_in/respond_to.rb +7 -1
  26. data/lib/rspec/matchers/built_in/satisfy.rb +7 -1
  27. data/lib/rspec/matchers/built_in/throw_symbol.rb +10 -2
  28. data/lib/rspec/matchers/built_in/yield.rb +25 -3
  29. data/lib/rspec/matchers/built_in.rb +2 -2
  30. data/lib/rspec/matchers/differentiate_block_method_types.rb +55 -0
  31. data/lib/rspec/matchers/dsl.rb +2 -1
  32. data/lib/rspec/matchers/match_aliases.rb +22 -0
  33. data/lib/rspec/matchers/matcher.rb +131 -10
  34. data/lib/rspec/matchers/operator_matcher.rb +70 -70
  35. data/lib/rspec/matchers/pretty.rb +4 -0
  36. data/lib/rspec/matchers/test_unit_integration.rb +22 -5
  37. data/lib/rspec/matchers.rb +41 -7
  38. data/lib/rspec-expectations.rb +5 -0
  39. data/spec/rspec/{matchers → expectations}/configuration_spec.rb +21 -2
  40. data/spec/rspec/expectations/expectation_target_spec.rb +62 -0
  41. data/spec/rspec/expectations/extensions/kernel_spec.rb +4 -0
  42. data/spec/rspec/expectations/handler_spec.rb +1 -1
  43. data/spec/rspec/expectations/syntax_spec.rb +6 -6
  44. data/spec/rspec/expectations_spec.rb +22 -1
  45. data/spec/rspec/matchers/base_matcher_spec.rb +15 -21
  46. data/spec/rspec/matchers/be_close_spec.rb +4 -1
  47. data/spec/rspec/matchers/be_spec.rb +105 -10
  48. data/spec/rspec/matchers/change_spec.rb +76 -1
  49. data/spec/rspec/matchers/description_generation_spec.rb +22 -18
  50. data/spec/rspec/matchers/differentiate_block_method_types_spec.rb +39 -0
  51. data/spec/rspec/matchers/eq_spec.rb +1 -1
  52. data/spec/rspec/matchers/has_spec.rb +24 -0
  53. data/spec/rspec/matchers/have_spec.rb +399 -1
  54. data/spec/rspec/matchers/matcher_spec.rb +213 -24
  55. data/spec/rspec/matchers/operator_matcher_spec.rb +28 -9
  56. data/spec/rspec/matchers/pretty_spec.rb +23 -0
  57. data/spec/rspec/matchers/raise_error_spec.rb +3 -3
  58. data/spec/rspec/matchers/throw_symbol_spec.rb +14 -14
  59. data/spec/spec_helper.rb +4 -2
  60. data/spec/support/helper_methods.rb +42 -0
  61. data/spec/support/shared_examples.rb +42 -0
  62. metadata +85 -64
  63. data/spec/rspec/matchers/matchers_spec.rb +0 -37
@@ -1,4 +1,5 @@
1
1
  require 'set'
2
+ require 'rspec/matchers/differentiate_block_method_types'
2
3
 
3
4
  module RSpec
4
5
  module Matchers
@@ -10,8 +11,7 @@ module RSpec
10
11
  include RSpec::Matchers::Pretty
11
12
  include RSpec::Matchers
12
13
 
13
- attr_reader :expected, :actual, :rescued_exception
14
- attr_accessor :matcher_execution_context
14
+ attr_reader :actual, :rescued_exception
15
15
 
16
16
  # @api private
17
17
  def initialize(name, &declarations)
@@ -19,17 +19,50 @@ module RSpec
19
19
  @declarations = declarations
20
20
  @actual = nil
21
21
  @diffable = false
22
+ @supports_block_expectations = false
22
23
  @expected_exception, @rescued_exception = nil, nil
23
24
  @match_for_should_not_block = nil
24
25
  @messages = {}
26
+ @define_block_executed = false
27
+ @block_method_differentiator = nil
28
+ @deprecated_methods = Set.new
29
+ @matcher_execution_context = nil
25
30
  end
26
31
 
27
32
  PERSISTENT_INSTANCE_VARIABLES = [
28
33
  :@name, :@declarations, :@diffable,
34
+ :@supports_block_expectations,
29
35
  :@match_block, :@match_for_should_not_block,
30
36
  :@expected_exception
31
37
  ].to_set
32
38
 
39
+ def expected
40
+ if @expected.size == 1
41
+ RSpec.warn_deprecation(
42
+ "Custom matchers in 3.x will set expected to be a single value "+
43
+ "(when provided as such) rather than an array. This may change "+
44
+ "the behaviour of your matcher.\n"+
45
+ "To continue to access this as an array use `expected_array`\n"+
46
+ "Called from: #{ RSpec::CallerFilter.first_non_rspec_line }\n\n"
47
+ )
48
+ end
49
+ @expected
50
+ end
51
+
52
+ def expected_as_array
53
+ @expected
54
+ end
55
+
56
+ def matcher_execution_context=(value)
57
+ RSpec.deprecate("`matcher_execution_context=` on custom matchers")
58
+ @matcher_execution_context = value
59
+ end
60
+
61
+ def matcher_execution_context
62
+ RSpec.deprecate("`matcher_execution_context` on custom matchers")
63
+ @matcher_execution_context
64
+ end
65
+
33
66
  # @api private
34
67
  def for_expected(*expected)
35
68
  @expected = expected
@@ -38,9 +71,14 @@ module RSpec
38
71
  instance_variable_set(ivar, nil) unless (PERSISTENT_INSTANCE_VARIABLES + [:@expected]).include?(ivar)
39
72
  end
40
73
  @messages = {}
74
+ @deprecated_methods = Set.new
75
+
76
+ @block_method_differentiator = DifferentiateBlockMethodTypes.new(*@expected, &@declarations)
41
77
  making_declared_methods_public do
42
78
  instance_eval_with_args(*@expected, &@declarations)
43
79
  end
80
+
81
+ @define_block_executed = true
44
82
  self
45
83
  end
46
84
  end
@@ -183,6 +221,10 @@ module RSpec
183
221
  @diffable = true
184
222
  end
185
223
 
224
+ def supports_block_expectations
225
+ @supports_block_expectations = true
226
+ end
227
+
186
228
  # Convenience for defining methods on this matcher to create a fluent
187
229
  # interface. The trick about fluent interfaces is that each method must
188
230
  # return self in order to chain methods together. `chain` handles that
@@ -214,6 +256,11 @@ module RSpec
214
256
  @diffable
215
257
  end
216
258
 
259
+ # @api private
260
+ def supports_block_expectations?
261
+ @supports_block_expectations
262
+ end
263
+
217
264
  # @api private
218
265
  # Used internally by +should_not+
219
266
  def does_not_match?(actual)
@@ -224,21 +271,51 @@ module RSpec
224
271
  end
225
272
 
226
273
  def respond_to?(method, include_private=false)
227
- super || matcher_execution_context.respond_to?(method, include_private)
274
+ super || @matcher_execution_context.respond_to?(method, include_private)
228
275
  end
229
276
 
230
277
  private
231
278
 
232
279
  def method_missing(method, *args, &block)
233
- if matcher_execution_context.respond_to?(method)
234
- matcher_execution_context.__send__ method, *args, &block
280
+ if @matcher_execution_context.respond_to?(method)
281
+ @matcher_execution_context.__send__ method, *args, &block
235
282
  else
236
283
  super(method, *args, &block)
237
284
  end
238
285
  end
239
286
 
240
- def include(*args)
241
- singleton_class.__send__(:include, *args)
287
+ def include(*modules)
288
+ return_value = singleton_class.__send__(:include, *modules)
289
+
290
+ modules.each do |mod|
291
+ mod.instance_methods.each do |name|
292
+ add_deprecation_warning_to(name,
293
+ "Calling a helper method (`#{name}`) from a module included in a custom matcher as a macro",
294
+ "`extend #{mod.name || "TheModule"}`",
295
+ "included in the custom matcher",
296
+ :unless
297
+ )
298
+ end
299
+ end
300
+
301
+ return_value
302
+ end
303
+
304
+ def extend(*modules)
305
+ return_value = super
306
+
307
+ modules.each do |mod|
308
+ mod.instance_methods.each do |name|
309
+ add_deprecation_warning_to(name,
310
+ "Calling a helper method (`#{name}`) from a module extended onto a custom matcher",
311
+ "`include #{mod.name || "TheModule"}`",
312
+ "extended onto the custom matcher",
313
+ :if
314
+ )
315
+ end
316
+ end unless @define_block_executed
317
+
318
+ return_value
242
319
  end
243
320
 
244
321
  def define_method(name, &block)
@@ -278,15 +355,15 @@ module RSpec
278
355
  end
279
356
 
280
357
  def default_description
281
- "#{name_to_sentence}#{expected_to_sentence}"
358
+ "#{name_to_sentence}#{to_sentence expected_as_array}"
282
359
  end
283
360
 
284
361
  def default_failure_message_for_should
285
- "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
362
+ "expected #{actual.inspect} to #{name_to_sentence}#{to_sentence expected_as_array}"
286
363
  end
287
364
 
288
365
  def default_failure_message_for_should_not
289
- "expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
366
+ "expected #{actual.inspect} not to #{name_to_sentence}#{to_sentence expected_as_array}"
290
367
  end
291
368
 
292
369
  unless method_defined?(:singleton_class)
@@ -294,6 +371,50 @@ module RSpec
294
371
  class << self; self; end
295
372
  end
296
373
  end
374
+
375
+ def singleton_method_added(name)
376
+ return unless @block_method_differentiator
377
+
378
+ if @block_method_differentiator.instance_methods.include?(name)
379
+ add_deprecation_warning_to(name,
380
+ "Calling a helper method (`#{name}`) defined as an instance method (using `def #{name}`) as a macro from a custom matcher `define` block",
381
+ "`def self.#{name}` (to define it as a singleton method)",
382
+ "defined in the custom matcher definition block",
383
+ :unless
384
+ )
385
+ elsif @block_method_differentiator.singleton_methods.include?(name)
386
+ add_deprecation_warning_to(name,
387
+ "Calling a helper method (`#{name}`) defined as a singleton method (using `def self.#{name}`) on a custom matcher",
388
+ "`def #{name}` (to define it as an instance method)",
389
+ "defined in the custom matcher definition block",
390
+ :if
391
+ )
392
+ end
393
+ end
394
+
395
+ def add_deprecation_warning_to(method_name, msg, replacement, extra_call_site_msg, condition)
396
+ return if @deprecated_methods.include?(method_name)
397
+ @deprecated_methods << method_name
398
+
399
+ aliased_name = aliased_name_for(method_name)
400
+ singleton_class.__send__(:alias_method, aliased_name, method_name)
401
+
402
+ singleton_class.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
403
+ def #{method_name}(*a, &b)
404
+ ::RSpec.deprecate(#{msg.inspect},
405
+ :replacement => #{replacement.inspect},
406
+ :call_site => CallerFilter.first_non_rspec_line + " and #{extra_call_site_msg} at #{CallerFilter.first_non_rspec_line}"
407
+ ) #{condition} @define_block_executed
408
+
409
+ __send__(#{aliased_name.inspect}, *a, &b)
410
+ end
411
+ EOS
412
+ end
413
+
414
+ def aliased_name_for(method_name)
415
+ target, punctuation = method_name.to_s.sub(/([?!=])$/, ''), $1
416
+ "#{target}_without_rspec_deprecation_warning#{punctuation}"
417
+ end
297
418
  end
298
419
  end
299
420
  end
@@ -1,95 +1,95 @@
1
1
  module RSpec
2
2
  module Matchers
3
- class OperatorMatcher
4
- class << self
5
- def registry
6
- @registry ||= {}
7
- end
3
+ module BuiltIn
4
+ class OperatorMatcher
5
+ class << self
6
+ def registry
7
+ @registry ||= {}
8
+ end
8
9
 
9
- def register(klass, operator, matcher)
10
- registry[klass] ||= {}
11
- registry[klass][operator] = matcher
12
- end
10
+ def register(klass, operator, matcher)
11
+ registry[klass] ||= {}
12
+ registry[klass][operator] = matcher
13
+ end
13
14
 
14
- def unregister(klass, operator)
15
- registry[klass] && registry[klass].delete(operator)
16
- end
15
+ def unregister(klass, operator)
16
+ registry[klass] && registry[klass].delete(operator)
17
+ end
17
18
 
18
- def get(klass, operator)
19
- klass.ancestors.each { |ancestor|
20
- matcher = registry[ancestor] && registry[ancestor][operator]
21
- return matcher if matcher
22
- }
19
+ def get(klass, operator)
20
+ klass.ancestors.each { |ancestor|
21
+ matcher = registry[ancestor] && registry[ancestor][operator]
22
+ return matcher if matcher
23
+ }
23
24
 
24
- nil
25
+ nil
26
+ end
25
27
  end
26
- end
27
28
 
28
- def initialize(actual)
29
- @actual = actual
30
- end
29
+ def initialize(actual)
30
+ @actual = actual
31
+ end
31
32
 
32
- def self.use_custom_matcher_or_delegate(operator)
33
- define_method(operator) do |expected|
34
- if uses_generic_implementation_of?(operator) && matcher = OperatorMatcher.get(@actual.class, operator)
35
- @actual.__send__(::RSpec::Matchers.last_should, matcher.new(expected))
36
- else
37
- eval_match(@actual, operator, expected)
33
+ def self.use_custom_matcher_or_delegate(operator)
34
+ define_method(operator) do |expected|
35
+ if uses_generic_implementation_of?(operator) && matcher = OperatorMatcher.get(@actual.class, operator)
36
+ @actual.__send__(::RSpec::Matchers.last_should, matcher.new(expected))
37
+ else
38
+ eval_match(@actual, operator, expected)
39
+ end
38
40
  end
39
- end
40
41
 
41
- negative_operator = operator.sub(/^=/, '!')
42
- if negative_operator != operator && respond_to?(negative_operator)
43
- define_method(negative_operator) do |expected|
44
- opposite_should = ::RSpec::Matchers.last_should == :should ? :should_not : :should
45
- raise "RSpec does not support `#{::RSpec::Matchers.last_should} #{negative_operator} expected`. " +
46
- "Use `#{opposite_should} #{operator} expected` instead."
42
+ negative_operator = operator.sub(/^=/, '!')
43
+ if negative_operator != operator && respond_to?(negative_operator)
44
+ define_method(negative_operator) do |expected|
45
+ opposite_should = ::RSpec::Matchers.last_should == :should ? :should_not : :should
46
+ raise "RSpec does not support `#{::RSpec::Matchers.last_should} #{negative_operator} expected`. " +
47
+ "Use `#{opposite_should} #{operator} expected` instead."
48
+ end
47
49
  end
48
50
  end
49
- end
50
51
 
51
- ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator|
52
- use_custom_matcher_or_delegate operator
53
- end
52
+ ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator|
53
+ use_custom_matcher_or_delegate operator
54
+ end
54
55
 
55
- def fail_with_message(message)
56
- RSpec::Expectations.fail_with(message, @expected, @actual)
57
- end
56
+ def fail_with_message(message)
57
+ RSpec::Expectations.fail_with(message, @expected, @actual)
58
+ end
58
59
 
59
- def description
60
- "#{@operator} #{@expected.inspect}"
61
- end
60
+ def description
61
+ "#{@operator} #{@expected.inspect}"
62
+ end
62
63
 
63
- private
64
+ private
64
65
 
65
- if Method.method_defined?(:owner) # 1.8.6 lacks Method#owner :-(
66
- def uses_generic_implementation_of?(op)
67
- Expectations.method_handle_for(@actual, op).owner == ::Kernel
68
- rescue NameError
69
- false
70
- end
71
- else
72
- def uses_generic_implementation_of?(op)
73
- # This is a bit of a hack, but:
74
- #
75
- # {}.method(:=~).to_s # => "#<Method: Hash(Kernel)#=~>"
76
- #
77
- # In the absence of Method#owner, this is the best we
78
- # can do to see if the method comes from Kernel.
79
- Expectations.method_handle_for(@actual, op).to_s.include?('(Kernel)')
80
- rescue NameError
81
- false
66
+ if Method.method_defined?(:owner) # 1.8.6 lacks Method#owner :-(
67
+ def uses_generic_implementation_of?(op)
68
+ Expectations.method_handle_for(@actual, op).owner == ::Kernel
69
+ rescue NameError
70
+ false
71
+ end
72
+ else
73
+ def uses_generic_implementation_of?(op)
74
+ # This is a bit of a hack, but:
75
+ #
76
+ # {}.method(:=~).to_s # => "#<Method: Hash(Kernel)#=~>"
77
+ #
78
+ # In the absence of Method#owner, this is the best we
79
+ # can do to see if the method comes from Kernel.
80
+ Expectations.method_handle_for(@actual, op).to_s.include?('(Kernel)')
81
+ rescue NameError
82
+ false
83
+ end
82
84
  end
83
- end
84
85
 
85
- def eval_match(actual, operator, expected)
86
- ::RSpec::Matchers.last_matcher = self
87
- @operator, @expected = operator, expected
88
- __delegate_operator(actual, operator, expected)
86
+ def eval_match(actual, operator, expected)
87
+ ::RSpec::Matchers.last_matcher = self
88
+ @operator, @expected = operator, expected
89
+ __delegate_operator(actual, operator, expected)
90
+ end
89
91
  end
90
- end
91
92
 
92
- module BuiltIn
93
93
  class PositiveOperatorMatcher < OperatorMatcher
94
94
  def __delegate_operator(actual, operator, expected)
95
95
  if actual.__send__(operator, expected)
@@ -21,6 +21,8 @@ module RSpec
21
21
  end
22
22
 
23
23
  def _pretty_print(array)
24
+ RSpec.deprecate("`RSpec::Matchers::Pretty#_pretty_print`",
25
+ :replacement => "`RSpec::Matchers::Pretty#to_sentence`")
24
26
  result = ""
25
27
  array.each_with_index do |item, index|
26
28
  if index < (array.length - 2)
@@ -43,6 +45,8 @@ module RSpec
43
45
  end
44
46
 
45
47
  def expected_to_sentence
48
+ RSpec.deprecate("`RSpec::Matchers::Pretty#expected_to_sentence`",
49
+ :replacement => "`RSpec::Matchers::Pretty#to_sentence(expected)`")
46
50
  to_sentence(@expected) if defined?(@expected)
47
51
  end
48
52
 
@@ -3,9 +3,26 @@
3
3
  # and a 1.9 bug can lead to infinite recursion from the `super` call in our
4
4
  # method_missing hook. See this gist for more info:
5
5
  # https://gist.github.com/845896
6
- if defined?(MiniTest::Unit::TestCase)
7
- MiniTest::Unit::TestCase.send(:include, RSpec::Matchers)
8
- end
9
- if defined?(Test::Unit::TestCase)
10
- Test::Unit::TestCase.send(:include, RSpec::Matchers)
6
+ if defined?(MiniTest::TestCase)
7
+ MiniTest::TestCase.add_setup_hook do |instance|
8
+ unless ::RSpec::Matchers === instance
9
+ ::RSpec.deprecate("rspec-expectations' built-in integration with minitest < 5.x",
10
+ :replacement => "`include RSpec::Matchers` from within `Minitest::TestCase`")
11
+
12
+ MiniTest::TestCase.send(:include, RSpec::Matchers)
13
+ end
14
+ end
15
+ elsif defined?(Test::Unit::TestCase)
16
+ Test::Unit::TestCase.class_eval do
17
+ def setup
18
+ unless ::RSpec::Matchers === self
19
+ ::RSpec.deprecate("rspec-expectations' built-in integration with Test::Unit",
20
+ :replacement => "`include RSpec::Matchers` from within `Test::Unit::TestCase`")
21
+
22
+ Test::Unit::TestCase.send(:include, RSpec::Matchers)
23
+ end
24
+
25
+ super if defined?(super)
26
+ end
27
+ end
11
28
  end
@@ -1,6 +1,7 @@
1
1
  require 'rspec/matchers/extensions/instance_eval_with_args'
2
2
  require 'rspec/matchers/pretty'
3
3
 
4
+ require 'rspec/matchers/match_aliases'
4
5
  require 'rspec/matchers/built_in'
5
6
  require 'rspec/matchers/matcher'
6
7
  require 'rspec/matchers/operator_matcher'
@@ -24,6 +25,7 @@ module RSpec
24
25
  # does_not_match?(actual)
25
26
  # failure_message_for_should_not
26
27
  # description
28
+ # supports_block_expectations?
27
29
  #
28
30
  # ## Predicates
29
31
  #
@@ -183,24 +185,42 @@ module RSpec
183
185
  obj.respond_to?(:failure_message_for_should) || obj.respond_to?(:failure_message)
184
186
  end
185
187
 
186
- # Passes if actual is truthy (anything but false or nil)
187
188
  def be_true
188
- BuiltIn::BeTrue.new
189
+ RSpec.deprecate("`be_true`", :replacement =>
190
+ "`be_truthy` (for Ruby's conditional semantics) or " +
191
+ "`be true` (for exact `== true` equality)"
192
+ )
193
+ BuiltIn::BeTruthy.new
189
194
  end
190
195
 
191
- # Passes if actual is falsy (false or nil)
192
196
  def be_false
193
- BuiltIn::BeFalse.new
197
+ RSpec.deprecate("`be_false`", :replacement =>
198
+ "`be_falsey` (for Ruby's conditional semantics) or " +
199
+ "`be false` (for exact `== false` equality)"
200
+ )
201
+ BuiltIn::BeFalsey.new
202
+ end
203
+
204
+ # Passes if actual is truthy (anything but false or nil)
205
+ def be_truthy
206
+ BuiltIn::BeTruthy.new
194
207
  end
195
208
 
209
+ # Passes if actual is falsy (false or nil)
210
+ def be_falsey
211
+ BuiltIn::BeFalsey.new
212
+ end
213
+
214
+ alias_method :be_falsy, :be_falsey
215
+
196
216
  # Passes if actual is nil
197
217
  def be_nil
198
218
  BuiltIn::BeNil.new
199
219
  end
200
220
 
201
221
  # @example
202
- # expect(actual).to be_true
203
- # expect(actual).to be_false
222
+ # expect(actual).to be_truthy
223
+ # expect(actual).to be_falsey
204
224
  # expect(actual).to be_nil
205
225
  # expect(actual).to be_[arbitrary_predicate](*args)
206
226
  # expect(actual).not_to be_nil
@@ -689,6 +709,20 @@ module RSpec
689
709
  BuiltIn::MatchArray.new(array)
690
710
  end
691
711
 
692
- OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
712
+ BuiltIn::OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
713
+
714
+ def self.const_missing(name)
715
+ case name
716
+ when :OperatorMatcher
717
+ RSpec.deprecate("`RSpec::Matchers::OperatorMatcher`",
718
+ :replacement => "`RSpec::Matchers::BuiltIn::OperatorMatcher`")
719
+ BuiltIn::OperatorMatcher
720
+ when :Configuration
721
+ RSpec.deprecate("`RSpec::Matchers::Configuration`",
722
+ :replacement => "`RSpec::Expectations::Configuration`")
723
+ Expectations::Configuration
724
+ else super
725
+ end
726
+ end
693
727
  end
694
728
  end
@@ -1 +1,6 @@
1
1
  require "rspec/expectations"
2
+
3
+ RSpec.deprecate("`require 'rspec-expectations'`",
4
+ :replacement => "`require 'rspec/expectations'`",
5
+ # we explcitly pass a caller because CallerFilter ignores this file
6
+ :call_site => caller[RUBY_PLATFORM == 'java' ? 2 : 0])
@@ -2,10 +2,10 @@ require 'spec_helper'
2
2
  require 'delegate'
3
3
 
4
4
  module RSpec
5
- module Matchers
5
+ module Expectations
6
6
  describe "RSpec::Matchers.configuration" do
7
7
  it 'returns a memoized configuration instance' do
8
- expect(RSpec::Matchers.configuration).to be_a(RSpec::Matchers::Configuration)
8
+ expect(RSpec::Matchers.configuration).to be_a(RSpec::Expectations::Configuration)
9
9
  expect(RSpec::Matchers.configuration).to be(RSpec::Matchers.configuration)
10
10
  end
11
11
  end
@@ -13,6 +13,25 @@ module RSpec
13
13
  describe Configuration do
14
14
  let(:config) { Configuration.new }
15
15
 
16
+ context "when accessing it using the old 2.x const name" do
17
+ it 'returns the new constant' do
18
+ allow_deprecation
19
+ expect(RSpec::Matchers::Configuration).to be(RSpec::Expectations::Configuration)
20
+ end
21
+
22
+ it 'issues a deprecation warning' do
23
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /RSpec::Matchers::Configuration/)
24
+ RSpec::Matchers::Configuration
25
+ end
26
+
27
+ it 'allows other undefined constant to raise errors like normal' do
28
+ expect_no_deprecation
29
+ expect {
30
+ RSpec::Matchers::FooBarBazz
31
+ }.to raise_error(NameError, /RSpec::Matchers::FooBarBazz/)
32
+ end
33
+ end
34
+
16
35
  describe "#backtrace_formatter" do
17
36
  let(:original_backtrace) { %w[ clean-me/a.rb other/file.rb clean-me/b.rb ] }
18
37
  let(:cleaned_backtrace) { %w[ other/file.rb ] }
@@ -22,6 +22,12 @@ module RSpec
22
22
  }.to raise_error(ArgumentError)
23
23
  end
24
24
 
25
+ it 'raises a wrong number of args ArgumentError when given two args' do
26
+ expect {
27
+ expect(1, 2)
28
+ }.to raise_error(ArgumentError, /wrong number of arg/)
29
+ end
30
+
25
31
  it 'raises an ArgumentError when given neither an argument nor a block' do
26
32
  expect {
27
33
  expect
@@ -76,6 +82,62 @@ module RSpec
76
82
  }.to raise_error(ArgumentError)
77
83
  end
78
84
  end
85
+
86
+ context "when passed a block" do
87
+ it 'can be used with a block matcher' do
88
+ expect { }.not_to raise_error
89
+ end
90
+
91
+ context 'when passed a value matcher' do
92
+ it 'issues a warning to instruct the user to use a value expression or fix the matcher (for `to`)' do
93
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /block expectation/)
94
+ expect { }.to be_an(Object)
95
+ end
96
+
97
+ it 'issues a warning to instruct the user to use a value expression or fix the matcher (for `not_to`)' do
98
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /block expectation/)
99
+ expect { }.not_to be_an(String)
100
+ end
101
+
102
+ it 'issues a warning to instruct the user to use a value expression or fix the matcher (for `to_not`)' do
103
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /block expectation/)
104
+ expect { }.to_not be_an(String)
105
+ end
106
+
107
+ it 'assumes a custom matcher that does not define `supports_block_expectations?` is not a block matcher (since it is relatively rare)' do
108
+ custom_matcher = Module.new do
109
+ def self.matches?(value); true; end
110
+ def self.description; "foo"; end
111
+ end
112
+
113
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /block expectation/)
114
+ expect(3).to custom_matcher # to show the custom matcher can be used as a matcher
115
+ expect { 3 }.to custom_matcher
116
+ end
117
+
118
+ it "uses the matcher's `description` in the warning" do
119
+ custom_matcher = Module.new do
120
+ def self.matches?(value); true; end
121
+ def self.description; "matcher-description"; end
122
+ end
123
+
124
+ expect_deprecation_with_replacement(/\(matcher-description\)/)
125
+ expect { }.to custom_matcher
126
+ end
127
+
128
+ context 'when the matcher does not define `description` (since it is an optional part of the protocol)' do
129
+ it 'uses `inspect` in the warning instead' do
130
+ custom_matcher = Module.new do
131
+ def self.matches?(value); true; end
132
+ def self.inspect; "matcher-inspect"; end
133
+ end
134
+
135
+ expect_deprecation_with_replacement(/\(matcher-inspect\)/)
136
+ expect { }.to custom_matcher
137
+ end
138
+ end
139
+ end
140
+ end
79
141
  end
80
142
  end
81
143
  end
@@ -32,6 +32,10 @@ describe Object, "#should" do
32
32
  true
33
33
  end
34
34
 
35
+ def respond_to?(name, include_all=false)
36
+ super || name == :proxied? || @target.respond_to?(name, include_all)
37
+ end
38
+
35
39
  def method_missing(name, *args)
36
40
  @target.send(name, *args)
37
41
  end
@@ -140,7 +140,7 @@ module RSpec
140
140
  actual = Object.new
141
141
  matcher.should_receive(:matches?).with(actual).and_return(false)
142
142
  matcher.stub(:negative_failure_message).and_return("ignore")
143
- expect(RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)).to be_false
143
+ expect(RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)).to be_falsey
144
144
  end
145
145
 
146
146