rspec-expectations 2.99.0.beta2 → 2.99.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Changelog.md +55 -32
- data/features/README.md +2 -1
- data/lib/rspec-expectations.rb +5 -0
- data/lib/rspec/expectations.rb +1 -1
- data/lib/rspec/{matchers → expectations}/configuration.rb +5 -3
- data/lib/rspec/expectations/expectation_target.rb +75 -8
- data/lib/rspec/expectations/syntax.rb +3 -5
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +12 -5
- data/lib/rspec/matchers/built_in/base_matcher.rb +11 -3
- data/lib/rspec/matchers/built_in/be.rb +15 -4
- data/lib/rspec/matchers/built_in/be_within.rb +6 -1
- data/lib/rspec/matchers/built_in/change.rb +4 -2
- data/lib/rspec/matchers/built_in/has.rb +38 -6
- 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 +5 -0
- data/lib/rspec/matchers/built_in/respond_to.rb +5 -0
- data/lib/rspec/matchers/built_in/satisfy.rb +5 -0
- data/lib/rspec/matchers/built_in/throw_symbol.rb +8 -1
- data/lib/rspec/matchers/built_in/yield.rb +21 -1
- data/lib/rspec/matchers/dsl.rb +2 -1
- data/lib/rspec/matchers/matcher.rb +28 -7
- data/lib/rspec/matchers/pretty.rb +4 -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_spec.rb +7 -0
- data/spec/rspec/matchers/be_spec.rb +21 -0
- data/spec/rspec/matchers/description_generation_spec.rb +1 -1
- data/spec/rspec/matchers/has_spec.rb +24 -0
- data/spec/rspec/matchers/matcher_spec.rb +52 -0
- data/spec/rspec/matchers/pretty_spec.rb +23 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/support/helper_methods.rb +6 -0
- metadata +64 -75
@@ -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/matchers.rb
CHANGED
@@ -25,6 +25,7 @@ module RSpec
|
|
25
25
|
# does_not_match?(actual)
|
26
26
|
# failure_message_for_should_not
|
27
27
|
# description
|
28
|
+
# supports_block_expectations?
|
28
29
|
#
|
29
30
|
# ## Predicates
|
30
31
|
#
|
@@ -711,11 +712,17 @@ module RSpec
|
|
711
712
|
BuiltIn::OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
|
712
713
|
|
713
714
|
def self.const_missing(name)
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
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
|
719
726
|
end
|
720
727
|
end
|
721
728
|
end
|
@@ -40,12 +40,12 @@ module RSpec
|
|
40
40
|
|
41
41
|
def failure_message_for_should
|
42
42
|
assert_ivars :@actual
|
43
|
-
"expected #{@actual.inspect} to #{name_to_sentence}#{
|
43
|
+
"expected #{@actual.inspect} to #{name_to_sentence}#{to_sentence expected}"
|
44
44
|
end
|
45
45
|
|
46
46
|
def failure_message_for_should_not
|
47
47
|
assert_ivars :@actual
|
48
|
-
"expected #{@actual.inspect} not to #{name_to_sentence}#{
|
48
|
+
"expected #{@actual.inspect} not to #{name_to_sentence}#{to_sentence expected}"
|
49
49
|
end
|
50
50
|
|
51
51
|
def description
|
@@ -56,7 +56,15 @@ module RSpec
|
|
56
56
|
false
|
57
57
|
end
|
58
58
|
|
59
|
-
private
|
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
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
60
68
|
|
61
69
|
def assert_ivars *ivars
|
62
70
|
raise "#{self.class.name} needs to supply #{to_sentence ivars}" unless ivars.all? { |v| instance_variables.map(&:intern).include? v }
|
@@ -149,13 +149,17 @@ it is a bit confusing.
|
|
149
149
|
end
|
150
150
|
|
151
151
|
begin
|
152
|
-
|
152
|
+
@result = actual.__send__(predicate, *@args, &@block)
|
153
|
+
check_respond_to(predicate)
|
154
|
+
return @result
|
153
155
|
rescue NameError => predicate_missing_error
|
154
156
|
"this needs to be here or rcov will not count this branch even though it's executed in a code example"
|
155
157
|
end
|
156
158
|
|
157
159
|
begin
|
158
|
-
|
160
|
+
@result = actual.__send__(present_tense_predicate, *@args, &@block)
|
161
|
+
check_respond_to(present_tense_predicate)
|
162
|
+
return @result
|
159
163
|
rescue NameError
|
160
164
|
raise predicate_missing_error
|
161
165
|
end
|
@@ -175,10 +179,10 @@ it is a bit confusing.
|
|
175
179
|
"#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
|
176
180
|
end
|
177
181
|
|
178
|
-
|
182
|
+
private
|
179
183
|
|
180
184
|
# support 1.8.7
|
181
|
-
if methods.first
|
185
|
+
if String === methods.first
|
182
186
|
def is_private_on? actual
|
183
187
|
actual.private_methods.include? predicate.to_s
|
184
188
|
end
|
@@ -209,6 +213,13 @@ it is a bit confusing.
|
|
209
213
|
def prefix_to_sentence
|
210
214
|
split_words(@prefix)
|
211
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
|
212
223
|
end
|
213
224
|
end
|
214
225
|
end
|
@@ -41,7 +41,12 @@ module RSpec
|
|
41
41
|
"be within #{@delta}#{@unit} of #{@expected}"
|
42
42
|
end
|
43
43
|
|
44
|
-
private
|
44
|
+
# @private
|
45
|
+
def supports_block_expectations?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
45
50
|
|
46
51
|
def needs_subtractable
|
47
52
|
ArgumentError.new "The actual value (#{@actual.inspect}) must respond to `-`"
|
@@ -40,7 +40,6 @@ module RSpec
|
|
40
40
|
|
41
41
|
unless matches_before?
|
42
42
|
RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
|
43
|
-
|--------------------------------------------------------------------
|
44
43
|
|The semantics of `expect { }.not_to change { }.from()` are changing
|
45
44
|
|in RSpec 3. In RSpec 2.x, this would pass if the value changed but
|
46
45
|
|the starting value was not what you specified with `from()`. In
|
@@ -49,7 +48,6 @@ module RSpec
|
|
49
48
|
|
|
50
49
|
|You have an expectation that relies upon the old RSpec 2.x semantics
|
51
50
|
|at: #{CallerFilter.first_non_rspec_line}"
|
52
|
-
|--------------------------------------------------------------------
|
53
51
|
EOS
|
54
52
|
end
|
55
53
|
|
@@ -126,6 +124,10 @@ MESSAGE
|
|
126
124
|
"change ##{message}"
|
127
125
|
end
|
128
126
|
|
127
|
+
def supports_block_expectations?
|
128
|
+
true
|
129
|
+
end
|
130
|
+
|
129
131
|
private
|
130
132
|
|
131
133
|
def failure_message_for_expected_after
|
@@ -9,25 +9,50 @@ module RSpec
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def matches?(actual)
|
12
|
-
|
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
|
13
22
|
end
|
14
23
|
|
15
24
|
def failure_message_for_should
|
16
|
-
"expected ##{predicate
|
25
|
+
"expected ##{predicate}#{failure_message_args_description} to return true, got false"
|
17
26
|
end
|
18
27
|
|
19
28
|
def failure_message_for_should_not
|
20
|
-
"expected ##{predicate
|
29
|
+
"expected ##{predicate}#{failure_message_args_description} to return false, got true"
|
21
30
|
end
|
22
31
|
|
23
32
|
def description
|
24
33
|
[method_description(@expected), args_description].compact.join(' ')
|
25
34
|
end
|
26
35
|
|
27
|
-
private
|
36
|
+
# @private
|
37
|
+
def supports_block_expectations?
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
28
42
|
|
29
|
-
|
30
|
-
|
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
|
31
56
|
end
|
32
57
|
|
33
58
|
def method_description(method)
|
@@ -43,6 +68,13 @@ module RSpec
|
|
43
68
|
desc = args_description
|
44
69
|
"(#{desc})" if desc
|
45
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
|
46
78
|
end
|
47
79
|
end
|
48
80
|
end
|
@@ -66,7 +66,14 @@ module RSpec
|
|
66
66
|
"throw #{expected}"
|
67
67
|
end
|
68
68
|
|
69
|
-
private
|
69
|
+
# @api private
|
70
|
+
# Indicates this matcher matches against a block.
|
71
|
+
# @return [True]
|
72
|
+
def supports_block_expectations?
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
70
77
|
|
71
78
|
def expected(symbol_desc = 'a Symbol')
|
72
79
|
throw_description(@expected_symbol || symbol_desc, @expected_arg)
|
@@ -121,7 +121,12 @@ module RSpec
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
private
|
124
|
+
# @private
|
125
|
+
def supports_block_expectations?
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
125
130
|
|
126
131
|
def set_expected_yields_count(relativity, n)
|
127
132
|
@expectation_type = relativity
|
@@ -169,6 +174,11 @@ module RSpec
|
|
169
174
|
"expected given block not to yield with no arguments, but did"
|
170
175
|
end
|
171
176
|
|
177
|
+
# @private
|
178
|
+
def supports_block_expectations?
|
179
|
+
true
|
180
|
+
end
|
181
|
+
|
172
182
|
private
|
173
183
|
|
174
184
|
def failure_reason
|
@@ -207,6 +217,11 @@ module RSpec
|
|
207
217
|
desc
|
208
218
|
end
|
209
219
|
|
220
|
+
# @private
|
221
|
+
def supports_block_expectations?
|
222
|
+
true
|
223
|
+
end
|
224
|
+
|
210
225
|
private
|
211
226
|
|
212
227
|
def positive_failure_reason
|
@@ -282,6 +297,11 @@ module RSpec
|
|
282
297
|
desc
|
283
298
|
end
|
284
299
|
|
300
|
+
# @private
|
301
|
+
def supports_block_expectations?
|
302
|
+
true
|
303
|
+
end
|
304
|
+
|
285
305
|
private
|
286
306
|
|
287
307
|
def args_match?
|
data/lib/rspec/matchers/dsl.rb
CHANGED
@@ -7,7 +7,8 @@ module RSpec
|
|
7
7
|
matcher_template = RSpec::Matchers::DSL::Matcher.new(name, &declarations)
|
8
8
|
define_method name do |*expected|
|
9
9
|
matcher = matcher_template.for_expected(*expected)
|
10
|
-
|
10
|
+
@matcher_execution_context ||= self
|
11
|
+
matcher.instance_variable_set(:@matcher_execution_context, @matcher_execution_context)
|
11
12
|
matcher
|
12
13
|
end
|
13
14
|
end
|
@@ -12,7 +12,6 @@ module RSpec
|
|
12
12
|
include RSpec::Matchers
|
13
13
|
|
14
14
|
attr_reader :actual, :rescued_exception
|
15
|
-
attr_accessor :matcher_execution_context
|
16
15
|
|
17
16
|
# @api private
|
18
17
|
def initialize(name, &declarations)
|
@@ -20,16 +19,19 @@ module RSpec
|
|
20
19
|
@declarations = declarations
|
21
20
|
@actual = nil
|
22
21
|
@diffable = false
|
22
|
+
@supports_block_expectations = false
|
23
23
|
@expected_exception, @rescued_exception = nil, nil
|
24
24
|
@match_for_should_not_block = nil
|
25
25
|
@messages = {}
|
26
26
|
@define_block_executed = false
|
27
27
|
@block_method_differentiator = nil
|
28
28
|
@deprecated_methods = Set.new
|
29
|
+
@matcher_execution_context = nil
|
29
30
|
end
|
30
31
|
|
31
32
|
PERSISTENT_INSTANCE_VARIABLES = [
|
32
33
|
:@name, :@declarations, :@diffable,
|
34
|
+
:@supports_block_expectations,
|
33
35
|
:@match_block, :@match_for_should_not_block,
|
34
36
|
:@expected_exception
|
35
37
|
].to_set
|
@@ -51,6 +53,16 @@ module RSpec
|
|
51
53
|
@expected
|
52
54
|
end
|
53
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
|
+
|
54
66
|
# @api private
|
55
67
|
def for_expected(*expected)
|
56
68
|
@expected = expected
|
@@ -209,6 +221,10 @@ module RSpec
|
|
209
221
|
@diffable = true
|
210
222
|
end
|
211
223
|
|
224
|
+
def supports_block_expectations
|
225
|
+
@supports_block_expectations = true
|
226
|
+
end
|
227
|
+
|
212
228
|
# Convenience for defining methods on this matcher to create a fluent
|
213
229
|
# interface. The trick about fluent interfaces is that each method must
|
214
230
|
# return self in order to chain methods together. `chain` handles that
|
@@ -240,6 +256,11 @@ module RSpec
|
|
240
256
|
@diffable
|
241
257
|
end
|
242
258
|
|
259
|
+
# @api private
|
260
|
+
def supports_block_expectations?
|
261
|
+
@supports_block_expectations
|
262
|
+
end
|
263
|
+
|
243
264
|
# @api private
|
244
265
|
# Used internally by +should_not+
|
245
266
|
def does_not_match?(actual)
|
@@ -250,14 +271,14 @@ module RSpec
|
|
250
271
|
end
|
251
272
|
|
252
273
|
def respond_to?(method, include_private=false)
|
253
|
-
super || matcher_execution_context.respond_to?(method, include_private)
|
274
|
+
super || @matcher_execution_context.respond_to?(method, include_private)
|
254
275
|
end
|
255
276
|
|
256
277
|
private
|
257
278
|
|
258
279
|
def method_missing(method, *args, &block)
|
259
|
-
if matcher_execution_context.respond_to?(method)
|
260
|
-
matcher_execution_context.__send__ method, *args, &block
|
280
|
+
if @matcher_execution_context.respond_to?(method)
|
281
|
+
@matcher_execution_context.__send__ method, *args, &block
|
261
282
|
else
|
262
283
|
super(method, *args, &block)
|
263
284
|
end
|
@@ -334,15 +355,15 @@ module RSpec
|
|
334
355
|
end
|
335
356
|
|
336
357
|
def default_description
|
337
|
-
"#{name_to_sentence}#{
|
358
|
+
"#{name_to_sentence}#{to_sentence expected_as_array}"
|
338
359
|
end
|
339
360
|
|
340
361
|
def default_failure_message_for_should
|
341
|
-
"expected #{actual.inspect} to #{name_to_sentence}#{
|
362
|
+
"expected #{actual.inspect} to #{name_to_sentence}#{to_sentence expected_as_array}"
|
342
363
|
end
|
343
364
|
|
344
365
|
def default_failure_message_for_should_not
|
345
|
-
"expected #{actual.inspect} not to #{name_to_sentence}#{
|
366
|
+
"expected #{actual.inspect} not to #{name_to_sentence}#{to_sentence expected_as_array}"
|
346
367
|
end
|
347
368
|
|
348
369
|
unless method_defined?(:singleton_class)
|