rspec-expectations 2.99.0.beta1 → 2.99.0.beta2

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 (38) hide show
  1. data/Changelog.md +35 -1
  2. data/features/step_definitions/additional_cli_steps.rb +10 -0
  3. data/features/test_frameworks/test_unit.feature +40 -0
  4. data/lib/rspec/expectations/caller_filter.rb +50 -45
  5. data/lib/rspec/expectations/deprecation.rb +8 -0
  6. data/lib/rspec/expectations/handler.rb +5 -1
  7. data/lib/rspec/expectations/version.rb +1 -1
  8. data/lib/rspec/matchers.rb +10 -1
  9. data/lib/rspec/matchers/be_close.rb +4 -1
  10. data/lib/rspec/matchers/built_in/base_matcher.rb +8 -9
  11. data/lib/rspec/matchers/built_in/be_within.rb +2 -1
  12. data/lib/rspec/matchers/built_in/change.rb +37 -1
  13. data/lib/rspec/matchers/built_in/has.rb +2 -1
  14. data/lib/rspec/matchers/built_in/have.rb +6 -2
  15. data/lib/rspec/matchers/built_in/raise_error.rb +2 -1
  16. data/lib/rspec/matchers/built_in/respond_to.rb +2 -1
  17. data/lib/rspec/matchers/built_in/satisfy.rb +2 -1
  18. data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -1
  19. data/lib/rspec/matchers/built_in/yield.rb +4 -2
  20. data/lib/rspec/matchers/match_aliases.rb +22 -0
  21. data/lib/rspec/matchers/matcher.rb +18 -1
  22. data/lib/rspec/matchers/operator_matcher.rb +70 -70
  23. data/lib/rspec/matchers/test_unit_integration.rb +22 -5
  24. data/spec/rspec/expectations_spec.rb +1 -1
  25. data/spec/rspec/matchers/base_matcher_spec.rb +27 -12
  26. data/spec/rspec/matchers/be_close_spec.rb +4 -1
  27. data/spec/rspec/matchers/be_spec.rb +2 -2
  28. data/spec/rspec/matchers/change_spec.rb +76 -1
  29. data/spec/rspec/matchers/equal_spec.rb +26 -0
  30. data/spec/rspec/matchers/have_spec.rb +26 -18
  31. data/spec/rspec/matchers/matcher_spec.rb +13 -0
  32. data/spec/rspec/matchers/operator_matcher_spec.rb +25 -6
  33. data/spec/spec_helper.rb +0 -21
  34. data/spec/support/helper_methods.rb +28 -3
  35. data/spec/support/shared_examples.rb +42 -0
  36. metadata +20 -8
  37. checksums.yaml +0 -15
  38. data/spec/rspec/matchers/matchers_spec.rb +0 -37
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class RaiseError
5
+ include MatchAliases
6
+
5
7
  def initialize(expected_error_or_message=Exception, expected_message=nil, &block)
6
8
  @block = block
7
9
  @actual_error = nil
@@ -51,7 +53,6 @@ module RSpec
51
53
  ensure
52
54
  return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
53
55
  end
54
- alias == matches?
55
56
 
56
57
  def does_not_match?(given_proc)
57
58
  !matches?(given_proc, :negative_expectation)
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class RespondTo
5
+ include MatchAliases
6
+
5
7
  def initialize(*names)
6
8
  @names = names
7
9
  @expected_arity = nil
@@ -10,7 +12,6 @@ module RSpec
10
12
  def matches?(actual)
11
13
  find_failing_method_names(actual, :reject).empty?
12
14
  end
13
- alias == matches?
14
15
 
15
16
  def does_not_match?(actual)
16
17
  find_failing_method_names(actual, :select).empty?
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Satisfy
5
+ include MatchAliases
6
+
5
7
  def initialize(&block)
6
8
  @block = block
7
9
  end
@@ -11,7 +13,6 @@ module RSpec
11
13
  @actual = actual
12
14
  @block.call(actual)
13
15
  end
14
- alias == matches?
15
16
 
16
17
  def failure_message_for_should
17
18
  "expected #{@actual} to satisfy block"
@@ -2,6 +2,8 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class ThrowSymbol
5
+ include MatchAliases
6
+
5
7
  def initialize(expected_symbol = nil, expected_arg=nil)
6
8
  @expected_symbol = expected_symbol
7
9
  @expected_arg = expected_arg
@@ -51,7 +53,6 @@ module RSpec
51
53
  end
52
54
  end
53
55
  end
54
- alias == matches?
55
56
 
56
57
  def failure_message_for_should
57
58
  "expected #{expected} to be thrown, got #{caught}"
@@ -181,6 +181,8 @@ module RSpec
181
181
  end
182
182
 
183
183
  class YieldWithArgs
184
+ include MatchAliases
185
+
184
186
  def initialize(*args)
185
187
  @expected = args
186
188
  end
@@ -190,7 +192,6 @@ module RSpec
190
192
  @actual = @probe.single_yield_args
191
193
  @probe.yielded_once?(:yield_with_args) && args_match?
192
194
  end
193
- alias == matches?
194
195
 
195
196
  def failure_message_for_should
196
197
  "expected given block to yield with arguments, but #{positive_failure_reason}"
@@ -251,6 +252,8 @@ module RSpec
251
252
  end
252
253
 
253
254
  class YieldSuccessiveArgs
255
+ include MatchAliases
256
+
254
257
  def initialize(*args)
255
258
  @expected = args
256
259
  end
@@ -260,7 +263,6 @@ module RSpec
260
263
  @actual = @probe.successive_yield_args
261
264
  args_match?
262
265
  end
263
- alias == matches?
264
266
 
265
267
  def failure_message_for_should
266
268
  "expected given block to yield successively with arguments, but yielded with unexpected arguments" +
@@ -0,0 +1,22 @@
1
+ module RSpec
2
+ module Matchers
3
+ module MatchAliases
4
+ def ==(other)
5
+ return true if equal?(other)
6
+
7
+ matched = matches?(other)
8
+
9
+ if matched
10
+ RSpec.deprecate("Using `matcher == value` as an alias for `#matches?`", :replacement => "`matcher === value`")
11
+ end
12
+
13
+ matched
14
+ end
15
+
16
+ def ===(other)
17
+ matches?(other)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -11,7 +11,7 @@ module RSpec
11
11
  include RSpec::Matchers::Pretty
12
12
  include RSpec::Matchers
13
13
 
14
- attr_reader :expected, :actual, :rescued_exception
14
+ attr_reader :actual, :rescued_exception
15
15
  attr_accessor :matcher_execution_context
16
16
 
17
17
  # @api private
@@ -34,6 +34,23 @@ module RSpec
34
34
  :@expected_exception
35
35
  ].to_set
36
36
 
37
+ def expected
38
+ if @expected.size == 1
39
+ RSpec.warn_deprecation(
40
+ "Custom matchers in 3.x will set expected to be a single value "+
41
+ "(when provided as such) rather than an array. This may change "+
42
+ "the behaviour of your matcher.\n"+
43
+ "To continue to access this as an array use `expected_array`\n"+
44
+ "Called from: #{ RSpec::CallerFilter.first_non_rspec_line }\n\n"
45
+ )
46
+ end
47
+ @expected
48
+ end
49
+
50
+ def expected_as_array
51
+ @expected
52
+ end
53
+
37
54
  # @api private
38
55
  def for_expected(*expected)
39
56
  @expected = expected
@@ -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)
@@ -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
@@ -50,7 +50,7 @@ module RSpec
50
50
  expect(Expectations.method_handle_for(object, :foo).call).to eq :bar
51
51
  end
52
52
 
53
- it 'fetches method definitions for basic objects', :if => RUBY_VERSION.to_i >= 2 do
53
+ it 'fetches method definitions for basic objects', :if => (RUBY_VERSION.to_i >= 2 && RUBY_ENGINE != 'rbx') do
54
54
  object = BasicClass.new
55
55
  expect(Expectations.method_handle_for(object, :foo).call).to eq :bar
56
56
  end
@@ -39,24 +39,39 @@ module RSpec::Matchers::BuiltIn
39
39
 
40
40
  end
41
41
 
42
- describe "#==" do
43
- it "responds the same way as matches?" do
44
- matcher = Class.new(BaseMatcher) do
45
- def initialize(expected)
46
- @expected = expected
47
- end
42
+ describe "#failure_message_for_should" do
43
+ context "when the parameter to .new is omitted" do
44
+ it "describes what was expected" do
45
+ matcher_class = Class.new(BaseMatcher) do
46
+ def name=(name)
47
+ @name = name
48
+ end
48
49
 
49
- def matches?(actual)
50
- (@actual = actual) == @expected
50
+ def match(expected, actual)
51
+ false
52
+ end
51
53
  end
54
+
55
+ matcher = matcher_class.new
56
+ matcher.name = "be something"
57
+ matcher.matches?("foo")
58
+ expect(matcher.failure_message_for_should).to eq('expected "foo" to be something')
52
59
  end
60
+ end
61
+ end
53
62
 
54
- expect(matcher.new(3).matches?(3)).to be_truthy
55
- expect(matcher.new(3)).to eq(3)
63
+ it_behaves_like "an RSpec matcher", :valid_value => 3, :invalid_value => 4 do
64
+ matcher_class = Class.new(BaseMatcher) do
65
+ def initialize(expected)
66
+ @expected = expected
67
+ end
56
68
 
57
- expect(matcher.new(3).matches?(4)).to be_falsey
58
- expect(matcher.new(3)).not_to eq(4)
69
+ def matches?(actual)
70
+ (@actual = actual) == @expected
71
+ end
59
72
  end
73
+
74
+ let(:matcher) { matcher_class.new(3) }
60
75
  end
61
76
  end
62
77
  end
@@ -8,7 +8,10 @@ module RSpec
8
8
  end
9
9
 
10
10
  it "is deprecated" do
11
- expect(RSpec).to receive(:deprecate).with(/be_close.*/, :replacement => "be_within(0.5).of(3.0)")
11
+ expect_deprecation_with_type('be_close(3.0, 0.5)',
12
+ 'be_within(0.5).of(3.0)',
13
+ 'the be_close matcher'
14
+ )
12
15
  be_close(3.0, 0.5)
13
16
  end
14
17
 
@@ -264,7 +264,7 @@ end
264
264
 
265
265
  describe "expect(...).to be_false" do
266
266
  it "is deprecated" do
267
- expect(RSpec).to receive(:deprecate).with(/be_false/, :replacement => match(/falsey.*false/))
267
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /be_false/)
268
268
  expect(false).to be_false
269
269
  end
270
270
 
@@ -288,7 +288,7 @@ end
288
288
 
289
289
  describe "expect(...).to be_true" do
290
290
  it "is deprecated" do
291
- expect(RSpec).to receive(:deprecate).with(/be_true/, :replacement => match(/truthy.*true/))
291
+ expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /be_true/)
292
292
  expect(true).to be_true
293
293
  end
294
294