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.
- checksums.yaml +15 -7
- data/Changelog.md +114 -31
- data/features/README.md +2 -1
- data/features/built_in_matchers/be.feature +40 -40
- 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 +60 -0
- data/lib/rspec/{matchers → expectations}/configuration.rb +5 -3
- data/lib/rspec/expectations/deprecation.rb +11 -15
- data/lib/rspec/expectations/expectation_target.rb +75 -8
- data/lib/rspec/expectations/handler.rb +5 -1
- data/lib/rspec/expectations/syntax.rb +3 -5
- data/lib/rspec/expectations/version.rb +1 -2
- data/lib/rspec/expectations.rb +1 -1
- data/lib/rspec/matchers/be_close.rb +4 -1
- data/lib/rspec/matchers/built_in/base_matcher.rb +10 -5
- data/lib/rspec/matchers/built_in/be.rb +38 -9
- data/lib/rspec/matchers/built_in/be_within.rb +8 -2
- data/lib/rspec/matchers/built_in/change.rb +39 -1
- data/lib/rspec/matchers/built_in/has.rb +40 -7
- data/lib/rspec/matchers/built_in/have.rb +151 -2
- data/lib/rspec/matchers/built_in/include.rb +1 -1
- data/lib/rspec/matchers/built_in/match_array.rb +1 -1
- data/lib/rspec/matchers/built_in/raise_error.rb +7 -1
- data/lib/rspec/matchers/built_in/respond_to.rb +7 -1
- data/lib/rspec/matchers/built_in/satisfy.rb +7 -1
- data/lib/rspec/matchers/built_in/throw_symbol.rb +10 -2
- data/lib/rspec/matchers/built_in/yield.rb +25 -3
- data/lib/rspec/matchers/built_in.rb +2 -2
- data/lib/rspec/matchers/differentiate_block_method_types.rb +55 -0
- data/lib/rspec/matchers/dsl.rb +2 -1
- data/lib/rspec/matchers/match_aliases.rb +22 -0
- data/lib/rspec/matchers/matcher.rb +131 -10
- data/lib/rspec/matchers/operator_matcher.rb +70 -70
- data/lib/rspec/matchers/pretty.rb +4 -0
- data/lib/rspec/matchers/test_unit_integration.rb +22 -5
- data/lib/rspec/matchers.rb +41 -7
- data/lib/rspec-expectations.rb +5 -0
- data/spec/rspec/{matchers → expectations}/configuration_spec.rb +21 -2
- data/spec/rspec/expectations/expectation_target_spec.rb +62 -0
- data/spec/rspec/expectations/extensions/kernel_spec.rb +4 -0
- data/spec/rspec/expectations/handler_spec.rb +1 -1
- data/spec/rspec/expectations/syntax_spec.rb +6 -6
- data/spec/rspec/expectations_spec.rb +22 -1
- data/spec/rspec/matchers/base_matcher_spec.rb +15 -21
- data/spec/rspec/matchers/be_close_spec.rb +4 -1
- data/spec/rspec/matchers/be_spec.rb +105 -10
- data/spec/rspec/matchers/change_spec.rb +76 -1
- data/spec/rspec/matchers/description_generation_spec.rb +22 -18
- data/spec/rspec/matchers/differentiate_block_method_types_spec.rb +39 -0
- data/spec/rspec/matchers/eq_spec.rb +1 -1
- data/spec/rspec/matchers/has_spec.rb +24 -0
- data/spec/rspec/matchers/have_spec.rb +399 -1
- data/spec/rspec/matchers/matcher_spec.rb +213 -24
- data/spec/rspec/matchers/operator_matcher_spec.rb +28 -9
- data/spec/rspec/matchers/pretty_spec.rb +23 -0
- data/spec/rspec/matchers/raise_error_spec.rb +3 -3
- data/spec/rspec/matchers/throw_symbol_spec.rb +14 -14
- data/spec/spec_helper.rb +4 -2
- data/spec/support/helper_methods.rb +42 -0
- data/spec/support/shared_examples.rb +42 -0
- metadata +85 -64
- data/spec/rspec/matchers/matchers_spec.rb +0 -37
|
@@ -1,27 +1,23 @@
|
|
|
1
|
+
require 'rspec/expectations/caller_filter' unless defined?(::RSpec::CallerFilter)
|
|
2
|
+
|
|
1
3
|
module RSpec
|
|
2
4
|
module Expectations
|
|
3
5
|
module Deprecation
|
|
4
|
-
RSPEC_LIBS = %w[
|
|
5
|
-
core
|
|
6
|
-
mocks
|
|
7
|
-
expectations
|
|
8
|
-
matchers
|
|
9
|
-
rails
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ]
|
|
13
|
-
|
|
14
|
-
LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
|
|
15
|
-
|
|
16
6
|
# @private
|
|
17
7
|
#
|
|
18
8
|
# Used internally to print deprecation warnings
|
|
19
9
|
def deprecate(deprecated, options={})
|
|
20
|
-
call_site = caller.find { |line| line !~ LIB_REGEX }
|
|
21
|
-
|
|
22
10
|
message = "DEPRECATION: #{deprecated} is deprecated."
|
|
23
11
|
message << " Use #{options[:replacement]} instead." if options[:replacement]
|
|
24
|
-
message << " Called from #{
|
|
12
|
+
message << " Called from #{CallerFilter.first_non_rspec_line}."
|
|
13
|
+
warn message
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @private
|
|
17
|
+
#
|
|
18
|
+
# Used internally to print deprecation warnings
|
|
19
|
+
def warn_deprecation(warning)
|
|
20
|
+
message = "\nDEPRECATION: #{warning}\n"
|
|
25
21
|
warn message
|
|
26
22
|
end
|
|
27
23
|
end
|
|
@@ -1,23 +1,48 @@
|
|
|
1
1
|
module RSpec
|
|
2
2
|
module Expectations
|
|
3
3
|
# Wraps the target of an expectation.
|
|
4
|
+
#
|
|
4
5
|
# @example
|
|
5
|
-
# expect(something)
|
|
6
|
+
# expect(something) # => ExpectationTarget wrapping something
|
|
7
|
+
# expect { do_something } # => ExpectationTarget wrapping the block
|
|
6
8
|
#
|
|
7
9
|
# # used with `to`
|
|
8
10
|
# expect(actual).to eq(3)
|
|
9
11
|
#
|
|
10
12
|
# # with `not_to`
|
|
11
13
|
# expect(actual).not_to eq(3)
|
|
14
|
+
#
|
|
15
|
+
# @note `ExpectationTarget` is not intended to be instantiated
|
|
16
|
+
# directly by users. Use `expect` instead.
|
|
12
17
|
class ExpectationTarget
|
|
13
18
|
class << self
|
|
14
19
|
attr_accessor :deprecated_should_enabled
|
|
15
20
|
alias deprecated_should_enabled? deprecated_should_enabled
|
|
16
21
|
end
|
|
17
22
|
|
|
23
|
+
# @private
|
|
24
|
+
# Used as a sentinel value to be able to tell when the user
|
|
25
|
+
# did not pass an argument. We can't use `nil` for that because
|
|
26
|
+
# `nil` is a valid value to pass.
|
|
27
|
+
UndefinedValue = Module.new
|
|
28
|
+
|
|
18
29
|
# @api private
|
|
19
|
-
def initialize(
|
|
20
|
-
@target =
|
|
30
|
+
def initialize(value)
|
|
31
|
+
@target = value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @private
|
|
35
|
+
def self.for(value, block)
|
|
36
|
+
if UndefinedValue.equal?(value)
|
|
37
|
+
unless block
|
|
38
|
+
raise ArgumentError, "You must pass either an argument or a block to `expect`."
|
|
39
|
+
end
|
|
40
|
+
BlockExpectationTarget.new(block)
|
|
41
|
+
elsif block
|
|
42
|
+
raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
|
|
43
|
+
else
|
|
44
|
+
new(value)
|
|
45
|
+
end
|
|
21
46
|
end
|
|
22
47
|
|
|
23
48
|
# Runs the given expectation, passing if `matcher` returns true.
|
|
@@ -30,7 +55,7 @@ module RSpec
|
|
|
30
55
|
# @return [Boolean] true if the expectation succeeds (else raises)
|
|
31
56
|
# @see RSpec::Matchers
|
|
32
57
|
def to(matcher=nil, message=nil, &block)
|
|
33
|
-
prevent_operator_matchers(:to
|
|
58
|
+
prevent_operator_matchers(:to) unless matcher
|
|
34
59
|
RSpec::Expectations::PositiveExpectationHandler.handle_matcher(@target, matcher, message, &block)
|
|
35
60
|
end
|
|
36
61
|
|
|
@@ -43,7 +68,7 @@ module RSpec
|
|
|
43
68
|
# @return [Boolean] false if the negative expectation succeeds (else raises)
|
|
44
69
|
# @see RSpec::Matchers
|
|
45
70
|
def not_to(matcher=nil, message=nil, &block)
|
|
46
|
-
prevent_operator_matchers(:not_to
|
|
71
|
+
prevent_operator_matchers(:not_to) unless matcher
|
|
47
72
|
RSpec::Expectations::NegativeExpectationHandler.handle_matcher(@target, matcher, message, &block)
|
|
48
73
|
end
|
|
49
74
|
alias to_not not_to
|
|
@@ -75,13 +100,55 @@ module RSpec
|
|
|
75
100
|
|
|
76
101
|
private
|
|
77
102
|
|
|
78
|
-
def prevent_operator_matchers(verb
|
|
79
|
-
return if matcher
|
|
80
|
-
|
|
103
|
+
def prevent_operator_matchers(verb)
|
|
81
104
|
raise ArgumentError, "The expect syntax does not support operator matchers, " +
|
|
82
105
|
"so you must pass a matcher to `##{verb}`."
|
|
83
106
|
end
|
|
84
107
|
end
|
|
108
|
+
|
|
109
|
+
# @private
|
|
110
|
+
# Validates the provided matcher to ensure it supports block
|
|
111
|
+
# expectations, in order to avoid user confusion when they
|
|
112
|
+
# use a block thinking the expectation will be on the return
|
|
113
|
+
# value of the block rather than the block itself.
|
|
114
|
+
class BlockExpectationTarget < ExpectationTarget
|
|
115
|
+
def to(matcher, message=nil, &block)
|
|
116
|
+
enforce_block_expectation(matcher)
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def not_to(matcher, message=nil, &block)
|
|
121
|
+
enforce_block_expectation(matcher)
|
|
122
|
+
super
|
|
123
|
+
end
|
|
124
|
+
alias to_not not_to
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
def enforce_block_expectation(matcher)
|
|
129
|
+
return if supports_block_expectations?(matcher)
|
|
130
|
+
|
|
131
|
+
RSpec.deprecate("Using a matcher in a block expectation expression " +
|
|
132
|
+
"(e.g. `expect { }.to matcher`) that does not implement " +
|
|
133
|
+
"`supports_block_expectations?`",
|
|
134
|
+
:replacement => "a value expectation expression " +
|
|
135
|
+
"(e.g. `expect(value).to matcher`) or implement " +
|
|
136
|
+
"`supports_block_expectations?` on the provided matcher " +
|
|
137
|
+
"(#{description_of matcher})")
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def supports_block_expectations?(matcher)
|
|
141
|
+
matcher.supports_block_expectations?
|
|
142
|
+
rescue NoMethodError
|
|
143
|
+
false
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def description_of(matcher)
|
|
147
|
+
matcher.description
|
|
148
|
+
rescue NoMethodError
|
|
149
|
+
matcher.inspect
|
|
150
|
+
end
|
|
151
|
+
end
|
|
85
152
|
end
|
|
86
153
|
end
|
|
87
154
|
|
|
@@ -31,7 +31,11 @@ module RSpec
|
|
|
31
31
|
matcher.failure_message
|
|
32
32
|
|
|
33
33
|
if matcher.respond_to?(:diffable?) && matcher.diffable?
|
|
34
|
-
|
|
34
|
+
if RSpec::Matchers::DSL::Matcher === matcher
|
|
35
|
+
::RSpec::Expectations.fail_with message, matcher.expected_as_array, matcher.actual
|
|
36
|
+
else
|
|
37
|
+
::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual
|
|
38
|
+
end
|
|
35
39
|
else
|
|
36
40
|
::RSpec::Expectations.fail_with message
|
|
37
41
|
end
|
|
@@ -79,11 +79,9 @@ module RSpec
|
|
|
79
79
|
def enable_expect(syntax_host = ::RSpec::Matchers)
|
|
80
80
|
return if expect_enabled?(syntax_host)
|
|
81
81
|
|
|
82
|
-
syntax_host.
|
|
83
|
-
def expect(
|
|
84
|
-
|
|
85
|
-
raise ArgumentError.new("You must pass an argument or a block to #expect but not both.") unless target.size == 1
|
|
86
|
-
::RSpec::Expectations::ExpectationTarget.new(target.first)
|
|
82
|
+
syntax_host.module_exec do
|
|
83
|
+
def expect(value=::RSpec::Expectations::ExpectationTarget::UndefinedValue, &block)
|
|
84
|
+
::RSpec::Expectations::ExpectationTarget.for(value, block)
|
|
87
85
|
end
|
|
88
86
|
end
|
|
89
87
|
|
data/lib/rspec/expectations.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'rspec/expectations/extensions'
|
|
2
2
|
require 'rspec/matchers'
|
|
3
3
|
require 'rspec/expectations/expectation_target'
|
|
4
|
-
require 'rspec/
|
|
4
|
+
require 'rspec/expectations/configuration'
|
|
5
5
|
require 'rspec/expectations/fail_with'
|
|
6
6
|
require 'rspec/expectations/errors'
|
|
7
7
|
require 'rspec/expectations/deprecation'
|
|
@@ -2,7 +2,10 @@ module RSpec
|
|
|
2
2
|
module Matchers
|
|
3
3
|
# @deprecated use +be_within+ instead.
|
|
4
4
|
def be_close(expected, delta)
|
|
5
|
-
RSpec.deprecate("be_close(#{expected}, #{delta})",
|
|
5
|
+
RSpec.deprecate("be_close(#{expected}, #{delta})",
|
|
6
|
+
:replacement => "be_within(#{delta}).of(#{expected})",
|
|
7
|
+
:type => 'the be_close matcher'
|
|
8
|
+
)
|
|
6
9
|
be_within(delta).of(expected)
|
|
7
10
|
end
|
|
8
11
|
end
|
|
@@ -13,6 +13,7 @@ module RSpec
|
|
|
13
13
|
# class. If/when this changes, we will announce it and remove this warning.
|
|
14
14
|
class BaseMatcher
|
|
15
15
|
include RSpec::Matchers::Pretty
|
|
16
|
+
include RSpec::Matchers::MatchAliases
|
|
16
17
|
|
|
17
18
|
UNDEFINED = Object.new.freeze
|
|
18
19
|
|
|
@@ -39,12 +40,12 @@ module RSpec
|
|
|
39
40
|
|
|
40
41
|
def failure_message_for_should
|
|
41
42
|
assert_ivars :@actual
|
|
42
|
-
"expected #{@actual.inspect} to #{name_to_sentence}#{
|
|
43
|
+
"expected #{@actual.inspect} to #{name_to_sentence}#{to_sentence expected}"
|
|
43
44
|
end
|
|
44
45
|
|
|
45
46
|
def failure_message_for_should_not
|
|
46
47
|
assert_ivars :@actual
|
|
47
|
-
"expected #{@actual.inspect} not to #{name_to_sentence}#{
|
|
48
|
+
"expected #{@actual.inspect} not to #{name_to_sentence}#{to_sentence expected}"
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
def description
|
|
@@ -55,11 +56,15 @@ module RSpec
|
|
|
55
56
|
false
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
# @api private
|
|
60
|
+
# Most matchers are value matchers (i.e. meant to work with `expect(value)`)
|
|
61
|
+
# rather than block matchers (i.e. meant to work with `expect { }`), so
|
|
62
|
+
# this defaults to false. Block matchers must override this to return true.
|
|
63
|
+
def supports_block_expectations?
|
|
64
|
+
false
|
|
60
65
|
end
|
|
61
66
|
|
|
62
|
-
|
|
67
|
+
private
|
|
63
68
|
|
|
64
69
|
def assert_ivars *ivars
|
|
65
70
|
raise "#{self.class.name} needs to supply #{to_sentence ivars}" unless ivars.all? { |v| instance_variables.map(&:intern).include? v }
|
|
@@ -3,31 +3,31 @@ require 'rspec/matchers/dsl'
|
|
|
3
3
|
module RSpec
|
|
4
4
|
module Matchers
|
|
5
5
|
module BuiltIn
|
|
6
|
-
class
|
|
6
|
+
class BeTruthy < BaseMatcher
|
|
7
7
|
def match(_, actual)
|
|
8
8
|
!!actual
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def failure_message_for_should
|
|
12
|
-
"expected:
|
|
12
|
+
"expected: truthy value\n got: #{actual.inspect}"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def failure_message_for_should_not
|
|
16
|
-
"expected:
|
|
16
|
+
"expected: falsey value\n got: #{actual.inspect}"
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
class
|
|
20
|
+
class BeFalsey < BaseMatcher
|
|
21
21
|
def match(_, actual)
|
|
22
22
|
!actual
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def failure_message_for_should
|
|
26
|
-
"expected:
|
|
26
|
+
"expected: falsey value\n got: #{actual.inspect}"
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def failure_message_for_should_not
|
|
30
|
-
"expected:
|
|
30
|
+
"expected: truthy value\n got: #{actual.inspect}"
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -141,14 +141,25 @@ it is a bit confusing.
|
|
|
141
141
|
|
|
142
142
|
def matches?(actual)
|
|
143
143
|
@actual = actual
|
|
144
|
+
|
|
145
|
+
if is_private_on?( @actual )
|
|
146
|
+
RSpec.deprecate "matching with be_#{predicate.to_s.gsub(/\?$/,'')} on private method #{predicate}",
|
|
147
|
+
:replacement => "`expect(object.send(#{predicate.inspect})).to be_true` or change the method's visibility to public",
|
|
148
|
+
:call_site => caller(0)[3]
|
|
149
|
+
end
|
|
150
|
+
|
|
144
151
|
begin
|
|
145
|
-
|
|
152
|
+
@result = actual.__send__(predicate, *@args, &@block)
|
|
153
|
+
check_respond_to(predicate)
|
|
154
|
+
return @result
|
|
146
155
|
rescue NameError => predicate_missing_error
|
|
147
156
|
"this needs to be here or rcov will not count this branch even though it's executed in a code example"
|
|
148
157
|
end
|
|
149
158
|
|
|
150
159
|
begin
|
|
151
|
-
|
|
160
|
+
@result = actual.__send__(present_tense_predicate, *@args, &@block)
|
|
161
|
+
check_respond_to(present_tense_predicate)
|
|
162
|
+
return @result
|
|
152
163
|
rescue NameError
|
|
153
164
|
raise predicate_missing_error
|
|
154
165
|
end
|
|
@@ -168,7 +179,18 @@ it is a bit confusing.
|
|
|
168
179
|
"#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
|
|
169
180
|
end
|
|
170
181
|
|
|
171
|
-
|
|
182
|
+
private
|
|
183
|
+
|
|
184
|
+
# support 1.8.7
|
|
185
|
+
if String === methods.first
|
|
186
|
+
def is_private_on? actual
|
|
187
|
+
actual.private_methods.include? predicate.to_s
|
|
188
|
+
end
|
|
189
|
+
else
|
|
190
|
+
def is_private_on? actual
|
|
191
|
+
actual.private_methods.include? predicate
|
|
192
|
+
end
|
|
193
|
+
end
|
|
172
194
|
|
|
173
195
|
def predicate
|
|
174
196
|
"#{@expected}?".to_sym
|
|
@@ -191,6 +213,13 @@ it is a bit confusing.
|
|
|
191
213
|
def prefix_to_sentence
|
|
192
214
|
split_words(@prefix)
|
|
193
215
|
end
|
|
216
|
+
|
|
217
|
+
def check_respond_to(method)
|
|
218
|
+
RSpec.deprecate(
|
|
219
|
+
"Matching with #{@prefix}#{@expected} on an object that doesn't respond to `#{method}`",
|
|
220
|
+
:replacement => "`respond_to_missing?` or `respond_to?` on your object"
|
|
221
|
+
) unless actual.respond_to?(method)
|
|
222
|
+
end
|
|
194
223
|
end
|
|
195
224
|
end
|
|
196
225
|
end
|
|
@@ -2,6 +2,8 @@ module RSpec
|
|
|
2
2
|
module Matchers
|
|
3
3
|
module BuiltIn
|
|
4
4
|
class BeWithin
|
|
5
|
+
include MatchAliases
|
|
6
|
+
|
|
5
7
|
def initialize(delta)
|
|
6
8
|
@delta = delta
|
|
7
9
|
end
|
|
@@ -12,7 +14,6 @@ module RSpec
|
|
|
12
14
|
raise needs_subtractable unless @actual.respond_to? :-
|
|
13
15
|
(@actual - @expected).abs <= @tolerance
|
|
14
16
|
end
|
|
15
|
-
alias == matches?
|
|
16
17
|
|
|
17
18
|
def of(expected)
|
|
18
19
|
@expected = expected
|
|
@@ -40,7 +41,12 @@ module RSpec
|
|
|
40
41
|
"be within #{@delta}#{@unit} of #{@expected}"
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
private
|
|
44
|
+
# @private
|
|
45
|
+
def supports_block_expectations?
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
44
50
|
|
|
45
51
|
def needs_subtractable
|
|
46
52
|
ArgumentError.new "The actual value (#{@actual.inspect}) must respond to `-`"
|
|
@@ -2,6 +2,8 @@ module RSpec
|
|
|
2
2
|
module Matchers
|
|
3
3
|
module BuiltIn
|
|
4
4
|
class Change
|
|
5
|
+
include MatchAliases
|
|
6
|
+
|
|
5
7
|
def initialize(receiver=nil, message=nil, &block)
|
|
6
8
|
@message = message
|
|
7
9
|
@value_proc = block || lambda {receiver.__send__(message)}
|
|
@@ -18,7 +20,39 @@ module RSpec
|
|
|
18
20
|
|
|
19
21
|
(!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
|
|
20
22
|
end
|
|
21
|
-
|
|
23
|
+
|
|
24
|
+
def does_not_match?(event_proc, &block)
|
|
25
|
+
expression = if @expected_delta
|
|
26
|
+
"by()"
|
|
27
|
+
elsif @minimum
|
|
28
|
+
"by_at_least()"
|
|
29
|
+
elsif @maximum
|
|
30
|
+
"by_at_most()"
|
|
31
|
+
elsif @eval_after
|
|
32
|
+
"to()"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if expression
|
|
36
|
+
RSpec.deprecate("`expect { }.not_to change { }.#{expression}`")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
matched_positively = matches?(event_proc, &block)
|
|
40
|
+
|
|
41
|
+
unless matches_before?
|
|
42
|
+
RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
|
|
43
|
+
|The semantics of `expect { }.not_to change { }.from()` are changing
|
|
44
|
+
|in RSpec 3. In RSpec 2.x, this would pass if the value changed but
|
|
45
|
+
|the starting value was not what you specified with `from()`. In
|
|
46
|
+
|RSpec 3, this will only pass if the starting value matches your
|
|
47
|
+
|`from()` value _and_ it has not changed.
|
|
48
|
+
|
|
|
49
|
+
|You have an expectation that relies upon the old RSpec 2.x semantics
|
|
50
|
+
|at: #{CallerFilter.first_non_rspec_line}"
|
|
51
|
+
EOS
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
!matched_positively
|
|
55
|
+
end
|
|
22
56
|
|
|
23
57
|
def raise_block_syntax_error
|
|
24
58
|
raise SyntaxError.new(<<-MESSAGE)
|
|
@@ -90,6 +124,10 @@ MESSAGE
|
|
|
90
124
|
"change ##{message}"
|
|
91
125
|
end
|
|
92
126
|
|
|
127
|
+
def supports_block_expectations?
|
|
128
|
+
true
|
|
129
|
+
end
|
|
130
|
+
|
|
93
131
|
private
|
|
94
132
|
|
|
95
133
|
def failure_message_for_expected_after
|
|
@@ -2,31 +2,57 @@ module RSpec
|
|
|
2
2
|
module Matchers
|
|
3
3
|
module BuiltIn
|
|
4
4
|
class Has
|
|
5
|
+
include MatchAliases
|
|
6
|
+
|
|
5
7
|
def initialize(expected, *args)
|
|
6
8
|
@expected, @args = expected, args
|
|
7
9
|
end
|
|
8
10
|
|
|
9
11
|
def matches?(actual)
|
|
10
|
-
|
|
12
|
+
method = predicate
|
|
13
|
+
|
|
14
|
+
if is_private_on?(actual)
|
|
15
|
+
RSpec.deprecate "matching with #{@expected} on private method #{predicate}",
|
|
16
|
+
:replacement => "`expect(object.send(#{predicate.inspect})).to be_true` or change the method's visibility to public"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
result = actual.__send__(method, *@args)
|
|
20
|
+
check_respond_to(actual, method)
|
|
21
|
+
result
|
|
11
22
|
end
|
|
12
|
-
alias == matches?
|
|
13
23
|
|
|
14
24
|
def failure_message_for_should
|
|
15
|
-
"expected ##{predicate
|
|
25
|
+
"expected ##{predicate}#{failure_message_args_description} to return true, got false"
|
|
16
26
|
end
|
|
17
27
|
|
|
18
28
|
def failure_message_for_should_not
|
|
19
|
-
"expected ##{predicate
|
|
29
|
+
"expected ##{predicate}#{failure_message_args_description} to return false, got true"
|
|
20
30
|
end
|
|
21
31
|
|
|
22
32
|
def description
|
|
23
33
|
[method_description(@expected), args_description].compact.join(' ')
|
|
24
34
|
end
|
|
25
35
|
|
|
26
|
-
private
|
|
36
|
+
# @private
|
|
37
|
+
def supports_block_expectations?
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
# support 1.8.7
|
|
44
|
+
if String === methods.first
|
|
45
|
+
def is_private_on? actual
|
|
46
|
+
actual.private_methods.include? predicate.to_s
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
def is_private_on? actual
|
|
50
|
+
actual.private_methods.include? predicate
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def predicate
|
|
55
|
+
"#{@expected.to_s.sub("have_","has_")}?".to_sym
|
|
30
56
|
end
|
|
31
57
|
|
|
32
58
|
def method_description(method)
|
|
@@ -42,6 +68,13 @@ module RSpec
|
|
|
42
68
|
desc = args_description
|
|
43
69
|
"(#{desc})" if desc
|
|
44
70
|
end
|
|
71
|
+
|
|
72
|
+
def check_respond_to(actual, method)
|
|
73
|
+
RSpec.deprecate(
|
|
74
|
+
"Matching with #{@expected} on an object that doesn't respond to `#{method}`",
|
|
75
|
+
:replacement => "`respond_to_missing?` or `respond_to?` on your object"
|
|
76
|
+
) unless actual.respond_to?(method)
|
|
77
|
+
end
|
|
45
78
|
end
|
|
46
79
|
end
|
|
47
80
|
end
|