rspec-expectations 2.99.0.beta1 → 2.99.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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