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.
- data/Changelog.md +35 -1
- data/features/step_definitions/additional_cli_steps.rb +10 -0
- data/features/test_frameworks/test_unit.feature +40 -0
- data/lib/rspec/expectations/caller_filter.rb +50 -45
- data/lib/rspec/expectations/deprecation.rb +8 -0
- data/lib/rspec/expectations/handler.rb +5 -1
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +10 -1
- data/lib/rspec/matchers/be_close.rb +4 -1
- data/lib/rspec/matchers/built_in/base_matcher.rb +8 -9
- data/lib/rspec/matchers/built_in/be_within.rb +2 -1
- data/lib/rspec/matchers/built_in/change.rb +37 -1
- data/lib/rspec/matchers/built_in/has.rb +2 -1
- data/lib/rspec/matchers/built_in/have.rb +6 -2
- data/lib/rspec/matchers/built_in/raise_error.rb +2 -1
- data/lib/rspec/matchers/built_in/respond_to.rb +2 -1
- data/lib/rspec/matchers/built_in/satisfy.rb +2 -1
- data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -1
- data/lib/rspec/matchers/built_in/yield.rb +4 -2
- data/lib/rspec/matchers/match_aliases.rb +22 -0
- data/lib/rspec/matchers/matcher.rb +18 -1
- data/lib/rspec/matchers/operator_matcher.rb +70 -70
- data/lib/rspec/matchers/test_unit_integration.rb +22 -5
- data/spec/rspec/expectations_spec.rb +1 -1
- data/spec/rspec/matchers/base_matcher_spec.rb +27 -12
- data/spec/rspec/matchers/be_close_spec.rb +4 -1
- data/spec/rspec/matchers/be_spec.rb +2 -2
- data/spec/rspec/matchers/change_spec.rb +76 -1
- data/spec/rspec/matchers/equal_spec.rb +26 -0
- data/spec/rspec/matchers/have_spec.rb +26 -18
- data/spec/rspec/matchers/matcher_spec.rb +13 -0
- data/spec/rspec/matchers/operator_matcher_spec.rb +25 -6
- data/spec/spec_helper.rb +0 -21
- data/spec/support/helper_methods.rb +28 -3
- data/spec/support/shared_examples.rb +42 -0
- metadata +20 -8
- checksums.yaml +0 -15
- 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 :
|
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
|
-
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module BuiltIn
|
4
|
+
class OperatorMatcher
|
5
|
+
class << self
|
6
|
+
def registry
|
7
|
+
@registry ||= {}
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
def register(klass, operator, matcher)
|
11
|
+
registry[klass] ||= {}
|
12
|
+
registry[klass][operator] = matcher
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def unregister(klass, operator)
|
16
|
+
registry[klass] && registry[klass].delete(operator)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
25
|
+
nil
|
26
|
+
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
def initialize(actual)
|
30
|
+
@actual = actual
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
52
|
+
['==', '===', '=~', '>', '>=', '<', '<='].each do |operator|
|
53
|
+
use_custom_matcher_or_delegate operator
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
56
|
+
def fail_with_message(message)
|
57
|
+
RSpec::Expectations.fail_with(message, @expected, @actual)
|
58
|
+
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
def description
|
61
|
+
"#{@operator} #{@expected.inspect}"
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
+
private
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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::
|
7
|
-
MiniTest::
|
8
|
-
|
9
|
-
|
10
|
-
|
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 "
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
58
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
291
|
+
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /be_true/)
|
292
292
|
expect(true).to be_true
|
293
293
|
end
|
294
294
|
|