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,4 +1,5 @@
|
|
|
1
1
|
require 'set'
|
|
2
|
+
require 'rspec/matchers/differentiate_block_method_types'
|
|
2
3
|
|
|
3
4
|
module RSpec
|
|
4
5
|
module Matchers
|
|
@@ -10,8 +11,7 @@ module RSpec
|
|
|
10
11
|
include RSpec::Matchers::Pretty
|
|
11
12
|
include RSpec::Matchers
|
|
12
13
|
|
|
13
|
-
attr_reader :
|
|
14
|
-
attr_accessor :matcher_execution_context
|
|
14
|
+
attr_reader :actual, :rescued_exception
|
|
15
15
|
|
|
16
16
|
# @api private
|
|
17
17
|
def initialize(name, &declarations)
|
|
@@ -19,17 +19,50 @@ module RSpec
|
|
|
19
19
|
@declarations = declarations
|
|
20
20
|
@actual = nil
|
|
21
21
|
@diffable = false
|
|
22
|
+
@supports_block_expectations = false
|
|
22
23
|
@expected_exception, @rescued_exception = nil, nil
|
|
23
24
|
@match_for_should_not_block = nil
|
|
24
25
|
@messages = {}
|
|
26
|
+
@define_block_executed = false
|
|
27
|
+
@block_method_differentiator = nil
|
|
28
|
+
@deprecated_methods = Set.new
|
|
29
|
+
@matcher_execution_context = nil
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
PERSISTENT_INSTANCE_VARIABLES = [
|
|
28
33
|
:@name, :@declarations, :@diffable,
|
|
34
|
+
:@supports_block_expectations,
|
|
29
35
|
:@match_block, :@match_for_should_not_block,
|
|
30
36
|
:@expected_exception
|
|
31
37
|
].to_set
|
|
32
38
|
|
|
39
|
+
def expected
|
|
40
|
+
if @expected.size == 1
|
|
41
|
+
RSpec.warn_deprecation(
|
|
42
|
+
"Custom matchers in 3.x will set expected to be a single value "+
|
|
43
|
+
"(when provided as such) rather than an array. This may change "+
|
|
44
|
+
"the behaviour of your matcher.\n"+
|
|
45
|
+
"To continue to access this as an array use `expected_array`\n"+
|
|
46
|
+
"Called from: #{ RSpec::CallerFilter.first_non_rspec_line }\n\n"
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
@expected
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def expected_as_array
|
|
53
|
+
@expected
|
|
54
|
+
end
|
|
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
|
+
|
|
33
66
|
# @api private
|
|
34
67
|
def for_expected(*expected)
|
|
35
68
|
@expected = expected
|
|
@@ -38,9 +71,14 @@ module RSpec
|
|
|
38
71
|
instance_variable_set(ivar, nil) unless (PERSISTENT_INSTANCE_VARIABLES + [:@expected]).include?(ivar)
|
|
39
72
|
end
|
|
40
73
|
@messages = {}
|
|
74
|
+
@deprecated_methods = Set.new
|
|
75
|
+
|
|
76
|
+
@block_method_differentiator = DifferentiateBlockMethodTypes.new(*@expected, &@declarations)
|
|
41
77
|
making_declared_methods_public do
|
|
42
78
|
instance_eval_with_args(*@expected, &@declarations)
|
|
43
79
|
end
|
|
80
|
+
|
|
81
|
+
@define_block_executed = true
|
|
44
82
|
self
|
|
45
83
|
end
|
|
46
84
|
end
|
|
@@ -183,6 +221,10 @@ module RSpec
|
|
|
183
221
|
@diffable = true
|
|
184
222
|
end
|
|
185
223
|
|
|
224
|
+
def supports_block_expectations
|
|
225
|
+
@supports_block_expectations = true
|
|
226
|
+
end
|
|
227
|
+
|
|
186
228
|
# Convenience for defining methods on this matcher to create a fluent
|
|
187
229
|
# interface. The trick about fluent interfaces is that each method must
|
|
188
230
|
# return self in order to chain methods together. `chain` handles that
|
|
@@ -214,6 +256,11 @@ module RSpec
|
|
|
214
256
|
@diffable
|
|
215
257
|
end
|
|
216
258
|
|
|
259
|
+
# @api private
|
|
260
|
+
def supports_block_expectations?
|
|
261
|
+
@supports_block_expectations
|
|
262
|
+
end
|
|
263
|
+
|
|
217
264
|
# @api private
|
|
218
265
|
# Used internally by +should_not+
|
|
219
266
|
def does_not_match?(actual)
|
|
@@ -224,21 +271,51 @@ module RSpec
|
|
|
224
271
|
end
|
|
225
272
|
|
|
226
273
|
def respond_to?(method, include_private=false)
|
|
227
|
-
super || matcher_execution_context.respond_to?(method, include_private)
|
|
274
|
+
super || @matcher_execution_context.respond_to?(method, include_private)
|
|
228
275
|
end
|
|
229
276
|
|
|
230
277
|
private
|
|
231
278
|
|
|
232
279
|
def method_missing(method, *args, &block)
|
|
233
|
-
if matcher_execution_context.respond_to?(method)
|
|
234
|
-
matcher_execution_context.__send__ method, *args, &block
|
|
280
|
+
if @matcher_execution_context.respond_to?(method)
|
|
281
|
+
@matcher_execution_context.__send__ method, *args, &block
|
|
235
282
|
else
|
|
236
283
|
super(method, *args, &block)
|
|
237
284
|
end
|
|
238
285
|
end
|
|
239
286
|
|
|
240
|
-
def include(*
|
|
241
|
-
singleton_class.__send__(:include, *
|
|
287
|
+
def include(*modules)
|
|
288
|
+
return_value = singleton_class.__send__(:include, *modules)
|
|
289
|
+
|
|
290
|
+
modules.each do |mod|
|
|
291
|
+
mod.instance_methods.each do |name|
|
|
292
|
+
add_deprecation_warning_to(name,
|
|
293
|
+
"Calling a helper method (`#{name}`) from a module included in a custom matcher as a macro",
|
|
294
|
+
"`extend #{mod.name || "TheModule"}`",
|
|
295
|
+
"included in the custom matcher",
|
|
296
|
+
:unless
|
|
297
|
+
)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
return_value
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def extend(*modules)
|
|
305
|
+
return_value = super
|
|
306
|
+
|
|
307
|
+
modules.each do |mod|
|
|
308
|
+
mod.instance_methods.each do |name|
|
|
309
|
+
add_deprecation_warning_to(name,
|
|
310
|
+
"Calling a helper method (`#{name}`) from a module extended onto a custom matcher",
|
|
311
|
+
"`include #{mod.name || "TheModule"}`",
|
|
312
|
+
"extended onto the custom matcher",
|
|
313
|
+
:if
|
|
314
|
+
)
|
|
315
|
+
end
|
|
316
|
+
end unless @define_block_executed
|
|
317
|
+
|
|
318
|
+
return_value
|
|
242
319
|
end
|
|
243
320
|
|
|
244
321
|
def define_method(name, &block)
|
|
@@ -278,15 +355,15 @@ module RSpec
|
|
|
278
355
|
end
|
|
279
356
|
|
|
280
357
|
def default_description
|
|
281
|
-
"#{name_to_sentence}#{
|
|
358
|
+
"#{name_to_sentence}#{to_sentence expected_as_array}"
|
|
282
359
|
end
|
|
283
360
|
|
|
284
361
|
def default_failure_message_for_should
|
|
285
|
-
"expected #{actual.inspect} to #{name_to_sentence}#{
|
|
362
|
+
"expected #{actual.inspect} to #{name_to_sentence}#{to_sentence expected_as_array}"
|
|
286
363
|
end
|
|
287
364
|
|
|
288
365
|
def default_failure_message_for_should_not
|
|
289
|
-
"expected #{actual.inspect} not to #{name_to_sentence}#{
|
|
366
|
+
"expected #{actual.inspect} not to #{name_to_sentence}#{to_sentence expected_as_array}"
|
|
290
367
|
end
|
|
291
368
|
|
|
292
369
|
unless method_defined?(:singleton_class)
|
|
@@ -294,6 +371,50 @@ module RSpec
|
|
|
294
371
|
class << self; self; end
|
|
295
372
|
end
|
|
296
373
|
end
|
|
374
|
+
|
|
375
|
+
def singleton_method_added(name)
|
|
376
|
+
return unless @block_method_differentiator
|
|
377
|
+
|
|
378
|
+
if @block_method_differentiator.instance_methods.include?(name)
|
|
379
|
+
add_deprecation_warning_to(name,
|
|
380
|
+
"Calling a helper method (`#{name}`) defined as an instance method (using `def #{name}`) as a macro from a custom matcher `define` block",
|
|
381
|
+
"`def self.#{name}` (to define it as a singleton method)",
|
|
382
|
+
"defined in the custom matcher definition block",
|
|
383
|
+
:unless
|
|
384
|
+
)
|
|
385
|
+
elsif @block_method_differentiator.singleton_methods.include?(name)
|
|
386
|
+
add_deprecation_warning_to(name,
|
|
387
|
+
"Calling a helper method (`#{name}`) defined as a singleton method (using `def self.#{name}`) on a custom matcher",
|
|
388
|
+
"`def #{name}` (to define it as an instance method)",
|
|
389
|
+
"defined in the custom matcher definition block",
|
|
390
|
+
:if
|
|
391
|
+
)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def add_deprecation_warning_to(method_name, msg, replacement, extra_call_site_msg, condition)
|
|
396
|
+
return if @deprecated_methods.include?(method_name)
|
|
397
|
+
@deprecated_methods << method_name
|
|
398
|
+
|
|
399
|
+
aliased_name = aliased_name_for(method_name)
|
|
400
|
+
singleton_class.__send__(:alias_method, aliased_name, method_name)
|
|
401
|
+
|
|
402
|
+
singleton_class.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
|
403
|
+
def #{method_name}(*a, &b)
|
|
404
|
+
::RSpec.deprecate(#{msg.inspect},
|
|
405
|
+
:replacement => #{replacement.inspect},
|
|
406
|
+
:call_site => CallerFilter.first_non_rspec_line + " and #{extra_call_site_msg} at #{CallerFilter.first_non_rspec_line}"
|
|
407
|
+
) #{condition} @define_block_executed
|
|
408
|
+
|
|
409
|
+
__send__(#{aliased_name.inspect}, *a, &b)
|
|
410
|
+
end
|
|
411
|
+
EOS
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def aliased_name_for(method_name)
|
|
415
|
+
target, punctuation = method_name.to_s.sub(/([?!=])$/, ''), $1
|
|
416
|
+
"#{target}_without_rspec_deprecation_warning#{punctuation}"
|
|
417
|
+
end
|
|
297
418
|
end
|
|
298
419
|
end
|
|
299
420
|
end
|
|
@@ -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)
|
|
@@ -21,6 +21,8 @@ module RSpec
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def _pretty_print(array)
|
|
24
|
+
RSpec.deprecate("`RSpec::Matchers::Pretty#_pretty_print`",
|
|
25
|
+
:replacement => "`RSpec::Matchers::Pretty#to_sentence`")
|
|
24
26
|
result = ""
|
|
25
27
|
array.each_with_index do |item, index|
|
|
26
28
|
if index < (array.length - 2)
|
|
@@ -43,6 +45,8 @@ module RSpec
|
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def expected_to_sentence
|
|
48
|
+
RSpec.deprecate("`RSpec::Matchers::Pretty#expected_to_sentence`",
|
|
49
|
+
:replacement => "`RSpec::Matchers::Pretty#to_sentence(expected)`")
|
|
46
50
|
to_sentence(@expected) if defined?(@expected)
|
|
47
51
|
end
|
|
48
52
|
|
|
@@ -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
|
data/lib/rspec/matchers.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'rspec/matchers/extensions/instance_eval_with_args'
|
|
2
2
|
require 'rspec/matchers/pretty'
|
|
3
3
|
|
|
4
|
+
require 'rspec/matchers/match_aliases'
|
|
4
5
|
require 'rspec/matchers/built_in'
|
|
5
6
|
require 'rspec/matchers/matcher'
|
|
6
7
|
require 'rspec/matchers/operator_matcher'
|
|
@@ -24,6 +25,7 @@ module RSpec
|
|
|
24
25
|
# does_not_match?(actual)
|
|
25
26
|
# failure_message_for_should_not
|
|
26
27
|
# description
|
|
28
|
+
# supports_block_expectations?
|
|
27
29
|
#
|
|
28
30
|
# ## Predicates
|
|
29
31
|
#
|
|
@@ -183,24 +185,42 @@ module RSpec
|
|
|
183
185
|
obj.respond_to?(:failure_message_for_should) || obj.respond_to?(:failure_message)
|
|
184
186
|
end
|
|
185
187
|
|
|
186
|
-
# Passes if actual is truthy (anything but false or nil)
|
|
187
188
|
def be_true
|
|
188
|
-
|
|
189
|
+
RSpec.deprecate("`be_true`", :replacement =>
|
|
190
|
+
"`be_truthy` (for Ruby's conditional semantics) or " +
|
|
191
|
+
"`be true` (for exact `== true` equality)"
|
|
192
|
+
)
|
|
193
|
+
BuiltIn::BeTruthy.new
|
|
189
194
|
end
|
|
190
195
|
|
|
191
|
-
# Passes if actual is falsy (false or nil)
|
|
192
196
|
def be_false
|
|
193
|
-
|
|
197
|
+
RSpec.deprecate("`be_false`", :replacement =>
|
|
198
|
+
"`be_falsey` (for Ruby's conditional semantics) or " +
|
|
199
|
+
"`be false` (for exact `== false` equality)"
|
|
200
|
+
)
|
|
201
|
+
BuiltIn::BeFalsey.new
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Passes if actual is truthy (anything but false or nil)
|
|
205
|
+
def be_truthy
|
|
206
|
+
BuiltIn::BeTruthy.new
|
|
194
207
|
end
|
|
195
208
|
|
|
209
|
+
# Passes if actual is falsy (false or nil)
|
|
210
|
+
def be_falsey
|
|
211
|
+
BuiltIn::BeFalsey.new
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
alias_method :be_falsy, :be_falsey
|
|
215
|
+
|
|
196
216
|
# Passes if actual is nil
|
|
197
217
|
def be_nil
|
|
198
218
|
BuiltIn::BeNil.new
|
|
199
219
|
end
|
|
200
220
|
|
|
201
221
|
# @example
|
|
202
|
-
# expect(actual).to
|
|
203
|
-
# expect(actual).to
|
|
222
|
+
# expect(actual).to be_truthy
|
|
223
|
+
# expect(actual).to be_falsey
|
|
204
224
|
# expect(actual).to be_nil
|
|
205
225
|
# expect(actual).to be_[arbitrary_predicate](*args)
|
|
206
226
|
# expect(actual).not_to be_nil
|
|
@@ -689,6 +709,20 @@ module RSpec
|
|
|
689
709
|
BuiltIn::MatchArray.new(array)
|
|
690
710
|
end
|
|
691
711
|
|
|
692
|
-
OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
|
|
712
|
+
BuiltIn::OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
|
|
713
|
+
|
|
714
|
+
def self.const_missing(name)
|
|
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
|
|
726
|
+
end
|
|
693
727
|
end
|
|
694
728
|
end
|
data/lib/rspec-expectations.rb
CHANGED
|
@@ -2,10 +2,10 @@ require 'spec_helper'
|
|
|
2
2
|
require 'delegate'
|
|
3
3
|
|
|
4
4
|
module RSpec
|
|
5
|
-
module
|
|
5
|
+
module Expectations
|
|
6
6
|
describe "RSpec::Matchers.configuration" do
|
|
7
7
|
it 'returns a memoized configuration instance' do
|
|
8
|
-
expect(RSpec::Matchers.configuration).to be_a(RSpec::
|
|
8
|
+
expect(RSpec::Matchers.configuration).to be_a(RSpec::Expectations::Configuration)
|
|
9
9
|
expect(RSpec::Matchers.configuration).to be(RSpec::Matchers.configuration)
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -13,6 +13,25 @@ module RSpec
|
|
|
13
13
|
describe Configuration do
|
|
14
14
|
let(:config) { Configuration.new }
|
|
15
15
|
|
|
16
|
+
context "when accessing it using the old 2.x const name" do
|
|
17
|
+
it 'returns the new constant' do
|
|
18
|
+
allow_deprecation
|
|
19
|
+
expect(RSpec::Matchers::Configuration).to be(RSpec::Expectations::Configuration)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'issues a deprecation warning' do
|
|
23
|
+
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /RSpec::Matchers::Configuration/)
|
|
24
|
+
RSpec::Matchers::Configuration
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'allows other undefined constant to raise errors like normal' do
|
|
28
|
+
expect_no_deprecation
|
|
29
|
+
expect {
|
|
30
|
+
RSpec::Matchers::FooBarBazz
|
|
31
|
+
}.to raise_error(NameError, /RSpec::Matchers::FooBarBazz/)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
16
35
|
describe "#backtrace_formatter" do
|
|
17
36
|
let(:original_backtrace) { %w[ clean-me/a.rb other/file.rb clean-me/b.rb ] }
|
|
18
37
|
let(:cleaned_backtrace) { %w[ other/file.rb ] }
|
|
@@ -22,6 +22,12 @@ module RSpec
|
|
|
22
22
|
}.to raise_error(ArgumentError)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
it 'raises a wrong number of args ArgumentError when given two args' do
|
|
26
|
+
expect {
|
|
27
|
+
expect(1, 2)
|
|
28
|
+
}.to raise_error(ArgumentError, /wrong number of arg/)
|
|
29
|
+
end
|
|
30
|
+
|
|
25
31
|
it 'raises an ArgumentError when given neither an argument nor a block' do
|
|
26
32
|
expect {
|
|
27
33
|
expect
|
|
@@ -76,6 +82,62 @@ module RSpec
|
|
|
76
82
|
}.to raise_error(ArgumentError)
|
|
77
83
|
end
|
|
78
84
|
end
|
|
85
|
+
|
|
86
|
+
context "when passed a block" do
|
|
87
|
+
it 'can be used with a block matcher' do
|
|
88
|
+
expect { }.not_to raise_error
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context 'when passed a value matcher' do
|
|
92
|
+
it 'issues a warning to instruct the user to use a value expression or fix the matcher (for `to`)' do
|
|
93
|
+
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /block expectation/)
|
|
94
|
+
expect { }.to be_an(Object)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'issues a warning to instruct the user to use a value expression or fix the matcher (for `not_to`)' do
|
|
98
|
+
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /block expectation/)
|
|
99
|
+
expect { }.not_to be_an(String)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'issues a warning to instruct the user to use a value expression or fix the matcher (for `to_not`)' do
|
|
103
|
+
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /block expectation/)
|
|
104
|
+
expect { }.to_not be_an(String)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'assumes a custom matcher that does not define `supports_block_expectations?` is not a block matcher (since it is relatively rare)' do
|
|
108
|
+
custom_matcher = Module.new do
|
|
109
|
+
def self.matches?(value); true; end
|
|
110
|
+
def self.description; "foo"; end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /block expectation/)
|
|
114
|
+
expect(3).to custom_matcher # to show the custom matcher can be used as a matcher
|
|
115
|
+
expect { 3 }.to custom_matcher
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "uses the matcher's `description` in the warning" do
|
|
119
|
+
custom_matcher = Module.new do
|
|
120
|
+
def self.matches?(value); true; end
|
|
121
|
+
def self.description; "matcher-description"; end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
expect_deprecation_with_replacement(/\(matcher-description\)/)
|
|
125
|
+
expect { }.to custom_matcher
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
context 'when the matcher does not define `description` (since it is an optional part of the protocol)' do
|
|
129
|
+
it 'uses `inspect` in the warning instead' do
|
|
130
|
+
custom_matcher = Module.new do
|
|
131
|
+
def self.matches?(value); true; end
|
|
132
|
+
def self.inspect; "matcher-inspect"; end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
expect_deprecation_with_replacement(/\(matcher-inspect\)/)
|
|
136
|
+
expect { }.to custom_matcher
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
79
141
|
end
|
|
80
142
|
end
|
|
81
143
|
end
|
|
@@ -140,7 +140,7 @@ module RSpec
|
|
|
140
140
|
actual = Object.new
|
|
141
141
|
matcher.should_receive(:matches?).with(actual).and_return(false)
|
|
142
142
|
matcher.stub(:negative_failure_message).and_return("ignore")
|
|
143
|
-
expect(RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)).to
|
|
143
|
+
expect(RSpec::Expectations::NegativeExpectationHandler.handle_matcher(actual, matcher)).to be_falsey
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
|