rspec-expectations 2.99.2 → 3.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +14 -6
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/Changelog.md +63 -104
- data/License.txt +1 -0
- data/README.md +14 -8
- data/features/README.md +1 -2
- data/features/built_in_matchers/README.md +3 -0
- data/features/built_in_matchers/be.feature +44 -44
- data/features/built_in_matchers/be_within.feature +1 -1
- data/features/built_in_matchers/comparisons.feature +97 -0
- data/features/built_in_matchers/cover.feature +3 -3
- data/features/built_in_matchers/end_with.feature +3 -3
- data/features/built_in_matchers/equality.feature +20 -23
- data/features/built_in_matchers/exist.feature +5 -5
- data/features/built_in_matchers/expect_error.feature +14 -14
- data/features/built_in_matchers/include.feature +15 -15
- data/features/built_in_matchers/match.feature +4 -5
- data/features/built_in_matchers/match_array.feature +37 -0
- data/features/built_in_matchers/predicates.feature +30 -6
- data/features/built_in_matchers/respond_to.feature +4 -4
- data/features/built_in_matchers/satisfy.feature +2 -2
- data/features/built_in_matchers/start_with.feature +3 -3
- data/features/built_in_matchers/types.feature +6 -6
- data/features/custom_matchers/access_running_example.feature +3 -3
- data/features/custom_matchers/define_matcher.feature +6 -34
- data/features/custom_matchers/define_matcher_outside_rspec.feature +2 -2
- data/features/custom_matchers/define_matcher_with_fluent_interface.feature +1 -1
- data/features/customized_message.feature +18 -1
- data/features/diffing.feature +3 -3
- data/features/implicit_docstrings.feature +9 -9
- data/features/step_definitions/additional_cli_steps.rb +0 -10
- data/features/support/env.rb +10 -3
- data/features/test_frameworks/test_unit.feature +0 -40
- data/lib/rspec-expectations.rb +0 -5
- data/lib/rspec/expectations.rb +4 -18
- data/lib/rspec/expectations/expectation_target.rb +10 -77
- data/lib/rspec/expectations/extensions.rb +0 -1
- data/lib/rspec/expectations/handler.rb +1 -5
- data/lib/rspec/expectations/syntax.rb +25 -5
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +7 -102
- data/lib/rspec/matchers/built_in/base_matcher.rb +10 -17
- data/lib/rspec/matchers/built_in/be.rb +5 -18
- data/lib/rspec/matchers/built_in/be_within.rb +2 -8
- data/lib/rspec/matchers/built_in/change.rb +1 -39
- data/lib/rspec/matchers/built_in/has.rb +7 -40
- 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 +44 -23
- data/lib/rspec/matchers/built_in/respond_to.rb +1 -7
- data/lib/rspec/matchers/built_in/satisfy.rb +1 -7
- data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -10
- data/lib/rspec/matchers/built_in/yield.rb +4 -25
- data/lib/rspec/matchers/compatibility.rb +2 -2
- data/lib/rspec/{expectations → matchers}/configuration.rb +9 -6
- data/lib/rspec/matchers/dsl.rb +2 -4
- data/lib/rspec/matchers/matcher.rb +163 -283
- data/lib/rspec/matchers/operator_matcher.rb +57 -71
- data/lib/rspec/matchers/pretty.rb +0 -4
- data/lib/rspec/matchers/test_unit_integration.rb +5 -22
- data/spec/rspec/expectations/expectation_target_spec.rb +0 -62
- data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -4
- data/spec/rspec/expectations_spec.rb +2 -43
- data/spec/rspec/matchers/base_matcher_spec.rb +12 -27
- data/spec/rspec/matchers/be_spec.rb +2 -71
- data/spec/rspec/matchers/change_spec.rb +1 -76
- data/spec/rspec/{expectations → matchers}/configuration_spec.rb +41 -21
- data/spec/rspec/matchers/description_generation_spec.rb +2 -21
- data/spec/rspec/matchers/equal_spec.rb +0 -26
- data/spec/rspec/matchers/has_spec.rb +0 -24
- data/spec/rspec/matchers/match_array_spec.rb +0 -13
- data/spec/rspec/matchers/matcher_spec.rb +325 -279
- data/spec/rspec/matchers/matchers_spec.rb +36 -0
- data/spec/rspec/matchers/operator_matcher_spec.rb +8 -27
- data/spec/rspec/matchers/raise_error_spec.rb +65 -209
- data/spec/rspec/matchers/yield_spec.rb +32 -9
- data/spec/spec_helper.rb +21 -6
- data/spec/support/classes.rb +7 -7
- data/spec/support/in_sub_process.rb +7 -8
- data/spec/support/shared_examples.rb +0 -42
- metadata +113 -84
- metadata.gz.sig +4 -0
- data/features/built_in_matchers/have.feature +0 -109
- data/features/built_in_matchers/operators.feature +0 -227
- data/lib/rspec/expectations/caller_filter.rb +0 -60
- data/lib/rspec/expectations/deprecation.rb +0 -27
- data/lib/rspec/expectations/extensions/array.rb +0 -9
- data/lib/rspec/matchers/be_close.rb +0 -12
- data/lib/rspec/matchers/built_in/have.rb +0 -273
- data/lib/rspec/matchers/differentiate_block_method_types.rb +0 -55
- data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
- data/lib/rspec/matchers/match_aliases.rb +0 -22
- data/spec/rspec/matchers/be_close_spec.rb +0 -25
- data/spec/rspec/matchers/differentiate_block_method_types_spec.rb +0 -39
- data/spec/rspec/matchers/have_spec.rb +0 -853
- data/spec/rspec/matchers/pretty_spec.rb +0 -23
- data/spec/support/helper_methods.rb +0 -42
@@ -2,8 +2,6 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class ThrowSymbol
|
5
|
-
include MatchAliases
|
6
|
-
|
7
5
|
def initialize(expected_symbol = nil, expected_arg=nil)
|
8
6
|
@expected_symbol = expected_symbol
|
9
7
|
@expected_arg = expected_arg
|
@@ -53,6 +51,7 @@ module RSpec
|
|
53
51
|
end
|
54
52
|
end
|
55
53
|
end
|
54
|
+
alias == matches?
|
56
55
|
|
57
56
|
def failure_message_for_should
|
58
57
|
"expected #{expected} to be thrown, got #{caught}"
|
@@ -66,14 +65,7 @@ module RSpec
|
|
66
65
|
"throw #{expected}"
|
67
66
|
end
|
68
67
|
|
69
|
-
|
70
|
-
# Indicates this matcher matches against a block.
|
71
|
-
# @return [True]
|
72
|
-
def supports_block_expectations?
|
73
|
-
true
|
74
|
-
end
|
75
|
-
|
76
|
-
private
|
68
|
+
private
|
77
69
|
|
78
70
|
def expected(symbol_desc = 'a Symbol')
|
79
71
|
throw_description(@expected_symbol || symbol_desc, @expected_arg)
|
@@ -24,6 +24,7 @@ module RSpec
|
|
24
24
|
Proc.new do |*args|
|
25
25
|
probe.num_yields += 1
|
26
26
|
probe.yielded_args << args
|
27
|
+
nil # to indicate the block does not return a meaningful value
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
@@ -121,12 +122,7 @@ module RSpec
|
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
124
|
-
|
125
|
-
def supports_block_expectations?
|
126
|
-
true
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
125
|
+
private
|
130
126
|
|
131
127
|
def set_expected_yields_count(relativity, n)
|
132
128
|
@expectation_type = relativity
|
@@ -174,11 +170,6 @@ module RSpec
|
|
174
170
|
"expected given block not to yield with no arguments, but did"
|
175
171
|
end
|
176
172
|
|
177
|
-
# @private
|
178
|
-
def supports_block_expectations?
|
179
|
-
true
|
180
|
-
end
|
181
|
-
|
182
173
|
private
|
183
174
|
|
184
175
|
def failure_reason
|
@@ -191,8 +182,6 @@ module RSpec
|
|
191
182
|
end
|
192
183
|
|
193
184
|
class YieldWithArgs
|
194
|
-
include MatchAliases
|
195
|
-
|
196
185
|
def initialize(*args)
|
197
186
|
@expected = args
|
198
187
|
end
|
@@ -202,6 +191,7 @@ module RSpec
|
|
202
191
|
@actual = @probe.single_yield_args
|
203
192
|
@probe.yielded_once?(:yield_with_args) && args_match?
|
204
193
|
end
|
194
|
+
alias == matches?
|
205
195
|
|
206
196
|
def failure_message_for_should
|
207
197
|
"expected given block to yield with arguments, but #{positive_failure_reason}"
|
@@ -217,11 +207,6 @@ module RSpec
|
|
217
207
|
desc
|
218
208
|
end
|
219
209
|
|
220
|
-
# @private
|
221
|
-
def supports_block_expectations?
|
222
|
-
true
|
223
|
-
end
|
224
|
-
|
225
210
|
private
|
226
211
|
|
227
212
|
def positive_failure_reason
|
@@ -267,8 +252,6 @@ module RSpec
|
|
267
252
|
end
|
268
253
|
|
269
254
|
class YieldSuccessiveArgs
|
270
|
-
include MatchAliases
|
271
|
-
|
272
255
|
def initialize(*args)
|
273
256
|
@expected = args
|
274
257
|
end
|
@@ -278,6 +261,7 @@ module RSpec
|
|
278
261
|
@actual = @probe.successive_yield_args
|
279
262
|
args_match?
|
280
263
|
end
|
264
|
+
alias == matches?
|
281
265
|
|
282
266
|
def failure_message_for_should
|
283
267
|
"expected given block to yield successively with arguments, but yielded with unexpected arguments" +
|
@@ -297,11 +281,6 @@ module RSpec
|
|
297
281
|
desc
|
298
282
|
end
|
299
283
|
|
300
|
-
# @private
|
301
|
-
def supports_block_expectations?
|
302
|
-
true
|
303
|
-
end
|
304
|
-
|
305
284
|
private
|
306
285
|
|
307
286
|
def args_match?
|
@@ -1,12 +1,12 @@
|
|
1
1
|
RSpec::Matchers.constants.each do |c|
|
2
2
|
if Class === (klass = RSpec::Matchers.const_get(c))
|
3
3
|
if klass.public_instance_methods.any? {|m| ['failure_message_for_should',:failure_message_for_should].include?(m)}
|
4
|
-
klass.
|
4
|
+
klass.class_exec do
|
5
5
|
alias_method :failure_message, :failure_message_for_should
|
6
6
|
end
|
7
7
|
end
|
8
8
|
if klass.public_instance_methods.any? {|m| ['failure_message_for_should_not',:failure_message_for_should_not].include?(m)}
|
9
|
-
klass.
|
9
|
+
klass.class_exec do
|
10
10
|
alias_method :negative_failure_message, :failure_message_for_should_not
|
11
11
|
end
|
12
12
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rspec/expectations/syntax'
|
2
2
|
|
3
3
|
module RSpec
|
4
|
-
module
|
4
|
+
module Matchers
|
5
5
|
# Provides configuration options for rspec-expectations.
|
6
6
|
class Configuration
|
7
7
|
# Configures the supported syntax.
|
@@ -87,6 +87,11 @@ module RSpec
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
def reset_syntaxes_to_default
|
91
|
+
self.syntax = [:should, :expect]
|
92
|
+
RSpec::Expectations::Syntax.warn_about_should!
|
93
|
+
end
|
94
|
+
|
90
95
|
# @api private
|
91
96
|
NullBacktraceFormatter = Module.new do
|
92
97
|
def self.format_backtrace(backtrace)
|
@@ -94,17 +99,15 @@ module RSpec
|
|
94
99
|
end
|
95
100
|
end
|
96
101
|
end
|
97
|
-
end
|
98
102
|
|
99
|
-
module Matchers
|
100
103
|
# The configuration object
|
101
|
-
# @return [RSpec::
|
104
|
+
# @return [RSpec::Matchers::Configuration] the configuration object
|
102
105
|
def self.configuration
|
103
|
-
@configuration ||=
|
106
|
+
@configuration ||= Configuration.new
|
104
107
|
end
|
105
108
|
|
106
109
|
# set default syntax
|
107
|
-
configuration.
|
110
|
+
configuration.reset_syntaxes_to_default
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
data/lib/rspec/matchers/dsl.rb
CHANGED
@@ -4,11 +4,9 @@ module RSpec
|
|
4
4
|
# Defines a custom matcher.
|
5
5
|
# @see RSpec::Matchers
|
6
6
|
def define(name, &declarations)
|
7
|
-
matcher_template = RSpec::Matchers::DSL::Matcher.new(name, &declarations)
|
8
7
|
define_method name do |*expected|
|
9
|
-
matcher =
|
10
|
-
@matcher_execution_context ||= self
|
11
|
-
matcher.instance_variable_set(:@matcher_execution_context, @matcher_execution_context)
|
8
|
+
matcher = RSpec::Matchers::DSL::Matcher.new(name, declarations, *expected)
|
9
|
+
matcher.matcher_execution_context = @matcher_execution_context ||= self
|
12
10
|
matcher
|
13
11
|
end
|
14
12
|
end
|
@@ -1,115 +1,18 @@
|
|
1
1
|
require 'set'
|
2
|
-
require 'rspec/matchers/differentiate_block_method_types'
|
3
2
|
|
4
3
|
module RSpec
|
5
4
|
module Matchers
|
6
5
|
module DSL
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
include RSpec::Matchers::Extensions::InstanceEvalWithArgs
|
11
|
-
include RSpec::Matchers::Pretty
|
12
|
-
include RSpec::Matchers
|
13
|
-
|
14
|
-
attr_reader :actual, :rescued_exception
|
15
|
-
|
16
|
-
# @api private
|
17
|
-
def initialize(name, &declarations)
|
18
|
-
@name = name
|
19
|
-
@declarations = declarations
|
20
|
-
@actual = nil
|
21
|
-
@diffable = false
|
22
|
-
@supports_block_expectations = false
|
23
|
-
@expected_exception, @rescued_exception = nil, nil
|
24
|
-
@match_for_should_not_block = nil
|
25
|
-
@messages = {}
|
26
|
-
@define_block_executed = false
|
27
|
-
@block_method_differentiator = nil
|
28
|
-
@deprecated_methods = Set.new
|
29
|
-
@matcher_execution_context = nil
|
30
|
-
end
|
31
|
-
|
32
|
-
PERSISTENT_INSTANCE_VARIABLES = [
|
33
|
-
:@name, :@declarations, :@diffable,
|
34
|
-
:@supports_block_expectations,
|
35
|
-
:@match_block, :@match_for_should_not_block,
|
36
|
-
:@expected_exception
|
37
|
-
].to_set
|
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_as_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
|
-
|
66
|
-
# @api private
|
67
|
-
def for_expected(*expected)
|
68
|
-
@expected = expected
|
69
|
-
dup.instance_eval do
|
70
|
-
instance_variables.map {|ivar| ivar.intern}.each do |ivar|
|
71
|
-
instance_variable_set(ivar, nil) unless (PERSISTENT_INSTANCE_VARIABLES + [:@expected]).include?(ivar)
|
72
|
-
end
|
73
|
-
@messages = {}
|
74
|
-
@deprecated_methods = Set.new
|
75
|
-
|
76
|
-
@block_method_differentiator = DifferentiateBlockMethodTypes.new(*@expected, &@declarations)
|
77
|
-
making_declared_methods_public do
|
78
|
-
instance_eval_with_args(*@expected, &@declarations)
|
79
|
-
end
|
80
|
-
|
81
|
-
@define_block_executed = true
|
82
|
-
self
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# @api private
|
87
|
-
# Used internally by +should+ and +should_not+.
|
88
|
-
def matches?(actual)
|
89
|
-
@actual = actual
|
90
|
-
if @expected_exception
|
91
|
-
begin
|
92
|
-
instance_eval_with_args(actual, &@match_block)
|
93
|
-
true
|
94
|
-
rescue @expected_exception => @rescued_exception
|
95
|
-
false
|
96
|
-
end
|
97
|
-
else
|
98
|
-
begin
|
99
|
-
instance_eval_with_args(actual, &@match_block)
|
100
|
-
rescue RSpec::Expectations::ExpectationNotMetError
|
101
|
-
false
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
6
|
+
# Contains the methods that are available from within the
|
7
|
+
# `RSpec::Matchers.define` DSL for creating custom matchers.
|
8
|
+
module Macros
|
106
9
|
# Stores the block that is used to determine whether this matcher passes
|
107
10
|
# or fails. The block should return a boolean value. When the matcher is
|
108
|
-
# passed to `
|
109
|
-
# passes. Similarly, when the matcher is passed to `
|
11
|
+
# passed to `expect(...).to` and the block returns `true`, then the expectation
|
12
|
+
# passes. Similarly, when the matcher is passed to `expect(...).not_to` and the
|
110
13
|
# block returns `false`, then the expectation passes.
|
111
14
|
#
|
112
|
-
# Use `match_for_should` when used in
|
15
|
+
# Use `match_for_should` when used in conjunction with
|
113
16
|
# `match_for_should_not`.
|
114
17
|
#
|
115
18
|
# @example
|
@@ -120,26 +23,35 @@ module RSpec
|
|
120
23
|
# end
|
121
24
|
# end
|
122
25
|
#
|
123
|
-
# 4.
|
124
|
-
# 3.
|
125
|
-
# 3.
|
126
|
-
# 4.
|
26
|
+
# expect(4).to be_even # passes
|
27
|
+
# expect(3).not_to be_even # passes
|
28
|
+
# expect(3).to be_even # fails
|
29
|
+
# expect(4).not_to be_even # fails
|
127
30
|
#
|
128
|
-
# @yield [Object] actual the actual value (
|
129
|
-
def match(&
|
130
|
-
|
31
|
+
# @yield [Object] actual the actual value (i.e. the value wrapped by `expect`)
|
32
|
+
def match(&match_block)
|
33
|
+
define_user_override(:matches?, match_block) do |actual|
|
34
|
+
begin
|
35
|
+
@actual = actual
|
36
|
+
super(*actual_arg_for(match_block))
|
37
|
+
rescue RSpec::Expectations::ExpectationNotMetError
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
131
41
|
end
|
42
|
+
alias match_for_should match
|
132
43
|
|
133
|
-
|
134
|
-
|
135
|
-
# Use this to define the block for a negative expectation (`should_not`)
|
44
|
+
# Use this to define the block for a negative expectation (`expect(...).not_to`)
|
136
45
|
# when the positive and negative forms require different handling. This
|
137
46
|
# is rarely necessary, but can be helpful, for example, when specifying
|
138
47
|
# asynchronous processes that require different timeouts.
|
139
48
|
#
|
140
|
-
# @yield [Object] actual the actual value (
|
141
|
-
def match_for_should_not(&
|
142
|
-
|
49
|
+
# @yield [Object] actual the actual value (i.e. the value wrapped by `expect`)
|
50
|
+
def match_for_should_not(&match_block)
|
51
|
+
define_user_override(:does_not_match?, match_block) do |actual|
|
52
|
+
@actual = actual
|
53
|
+
super(*actual_arg_for(match_block))
|
54
|
+
end
|
143
55
|
end
|
144
56
|
|
145
57
|
# Use this instead of `match` when the block will raise an exception
|
@@ -153,76 +65,82 @@ module RSpec
|
|
153
65
|
# end
|
154
66
|
# end
|
155
67
|
#
|
156
|
-
# email_validator.
|
157
|
-
|
158
|
-
|
159
|
-
|
68
|
+
# expect(email_validator).to accept_as_valid("person@company.com")
|
69
|
+
#
|
70
|
+
# @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
|
71
|
+
def match_unless_raises(expected_exception=Exception, &match_block)
|
72
|
+
define_user_override(:matches?, match_block) do |actual|
|
73
|
+
@actual = actual
|
74
|
+
begin
|
75
|
+
super(*actual_arg_for(match_block))
|
76
|
+
rescue expected_exception => @rescued_exception
|
77
|
+
false
|
78
|
+
else
|
79
|
+
true
|
80
|
+
end
|
81
|
+
end
|
160
82
|
end
|
161
83
|
|
162
|
-
#
|
163
|
-
#
|
164
|
-
# suit your needs.
|
84
|
+
# Customizes the failure messsage to use when this matcher is
|
85
|
+
# asked to positively match. Only use this when the message
|
86
|
+
# generated by default doesn't suit your needs.
|
165
87
|
#
|
166
88
|
# @example
|
167
89
|
#
|
168
90
|
# RSpec::Matchers.define :have_strength do |expected|
|
169
|
-
# match {
|
91
|
+
# match { your_match_logic }
|
170
92
|
#
|
171
93
|
# failure_message_for_should do |actual|
|
172
94
|
# "Expected strength of #{expected}, but had #{actual.strength}"
|
173
95
|
# end
|
174
96
|
# end
|
175
97
|
#
|
176
|
-
# @yield [Object] actual the actual object
|
177
|
-
def failure_message_for_should(&
|
178
|
-
|
98
|
+
# @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
|
99
|
+
def failure_message_for_should(&definition)
|
100
|
+
define_user_override(__method__, definition)
|
179
101
|
end
|
180
102
|
|
181
|
-
# Customize the failure messsage to use when this matcher is
|
182
|
-
#
|
183
|
-
# doesn't suit your needs.
|
103
|
+
# Customize the failure messsage to use when this matcher is asked
|
104
|
+
# to negatively match. Only use this when the message generated by
|
105
|
+
# default doesn't suit your needs.
|
184
106
|
#
|
185
107
|
# @example
|
186
108
|
#
|
187
109
|
# RSpec::Matchers.define :have_strength do |expected|
|
188
|
-
# match {
|
110
|
+
# match { your_match_logic }
|
189
111
|
#
|
190
112
|
# failure_message_for_should_not do |actual|
|
191
113
|
# "Expected not to have strength of #{expected}, but did"
|
192
114
|
# end
|
193
115
|
# end
|
194
116
|
#
|
195
|
-
# @yield [Object] actual the actual object
|
196
|
-
|
197
|
-
|
198
|
-
cache_or_call_cached(:failure_message_for_should_not, &block)
|
117
|
+
# @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
|
118
|
+
def failure_message_for_should_not(&definition)
|
119
|
+
define_user_override(__method__, definition)
|
199
120
|
end
|
200
121
|
|
201
|
-
|
202
122
|
# Customize the description to use for one-liners. Only use this when
|
203
123
|
# the description generated by default doesn't suit your needs.
|
204
124
|
#
|
205
125
|
# @example
|
206
126
|
#
|
207
127
|
# RSpec::Matchers.define :qualify_for do |expected|
|
208
|
-
# match {
|
128
|
+
# match { your_match_logic }
|
209
129
|
#
|
210
130
|
# description do
|
211
131
|
# "qualify for #{expected}"
|
212
132
|
# end
|
213
133
|
# end
|
214
|
-
|
215
|
-
|
134
|
+
#
|
135
|
+
# @yield [Object] actual the actual object (i.e. the value wrapped by `expect`)
|
136
|
+
def description(&definition)
|
137
|
+
define_user_override(__method__, definition)
|
216
138
|
end
|
217
139
|
|
218
140
|
# Tells the matcher to diff the actual and expected values in the failure
|
219
141
|
# message.
|
220
142
|
def diffable
|
221
|
-
|
222
|
-
end
|
223
|
-
|
224
|
-
def supports_block_expectations
|
225
|
-
@supports_block_expectations = true
|
143
|
+
define_method(:diffable?) { true }
|
226
144
|
end
|
227
145
|
|
228
146
|
# Convenience for defining methods on this matcher to create a fluent
|
@@ -242,178 +160,140 @@ module RSpec
|
|
242
160
|
# end
|
243
161
|
# end
|
244
162
|
#
|
245
|
-
# minor.
|
246
|
-
def chain(
|
247
|
-
|
248
|
-
|
163
|
+
# expect(minor).to have_errors_on(:age).with("Not old enough to participate")
|
164
|
+
def chain(name, &definition)
|
165
|
+
define_user_override(name, definition) do |*args, &block|
|
166
|
+
super(*args, &block)
|
249
167
|
self
|
250
168
|
end
|
251
169
|
end
|
252
170
|
|
253
|
-
|
254
|
-
# Used internally by objects returns by +should+ and +should_not+.
|
255
|
-
def diffable?
|
256
|
-
@diffable
|
257
|
-
end
|
171
|
+
private
|
258
172
|
|
259
|
-
#
|
260
|
-
|
261
|
-
|
173
|
+
# Does the following:
|
174
|
+
#
|
175
|
+
# - Defines the named method usign a user-provided block
|
176
|
+
# in @user_method_defs, which is included as an ancestor
|
177
|
+
# in the singleton class in which we eval the `define` block.
|
178
|
+
# - Defines an overriden definition for the same method
|
179
|
+
# usign the provided `our_def` block.
|
180
|
+
# - Provides a default `our_def` block for the common case
|
181
|
+
# of needing to call the user's definition with `@actual`
|
182
|
+
# as an arg, but only if their block's arity can handle it.
|
183
|
+
#
|
184
|
+
# This compiles the user block into an actual method, allowing
|
185
|
+
# them to use normal method constructs like `return`
|
186
|
+
# (e.g. for a early guard statement), while allowing us to define
|
187
|
+
# an override that can provide the wrapped handling
|
188
|
+
# (e.g. assigning `@actual`, rescueing errors, etc) and
|
189
|
+
# can `super` to the user's definition.
|
190
|
+
def define_user_override(method_name, user_def, &our_def)
|
191
|
+
@user_method_defs.__send__(:define_method, method_name, &user_def)
|
192
|
+
our_def ||= lambda { super(*actual_arg_for(user_def)) }
|
193
|
+
define_method(method_name, &our_def)
|
262
194
|
end
|
195
|
+
end
|
263
196
|
|
197
|
+
# Defines default implementations of the matcher
|
198
|
+
# protocol methods for custom matchers. You can
|
199
|
+
# override any of these using the {RSpec::Matchers::DSL::Macros Macros} methods
|
200
|
+
# from within an `RSpec::Matchers.define` block.
|
201
|
+
module DefaultImplementations
|
264
202
|
# @api private
|
265
|
-
# Used internally by
|
266
|
-
def
|
267
|
-
|
268
|
-
@match_for_should_not_block ?
|
269
|
-
instance_eval_with_args(actual, &@match_for_should_not_block) :
|
270
|
-
!matches?(actual)
|
271
|
-
end
|
272
|
-
|
273
|
-
def respond_to?(method, include_private=false)
|
274
|
-
super || @matcher_execution_context.respond_to?(method, include_private)
|
203
|
+
# Used internally by objects returns by `should` and `should_not`.
|
204
|
+
def diffable?
|
205
|
+
false
|
275
206
|
end
|
276
207
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
if @matcher_execution_context.respond_to?(method)
|
281
|
-
@matcher_execution_context.__send__ method, *args, &block
|
282
|
-
else
|
283
|
-
super(method, *args, &block)
|
284
|
-
end
|
208
|
+
# The default description.
|
209
|
+
def description
|
210
|
+
"#{name_to_sentence}#{expected_to_sentence}"
|
285
211
|
end
|
286
212
|
|
287
|
-
|
288
|
-
|
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
|
213
|
+
# The default failure message for positive expectations.
|
214
|
+
def failure_message_for_should
|
215
|
+
"expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
|
302
216
|
end
|
303
217
|
|
304
|
-
|
305
|
-
|
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
|
218
|
+
# The default failure message for negative expectations.
|
219
|
+
def failure_message_for_should_not
|
220
|
+
"expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
|
319
221
|
end
|
222
|
+
end
|
320
223
|
|
321
|
-
|
322
|
-
|
323
|
-
|
224
|
+
# The class used for custom matchers. The block passed to
|
225
|
+
# `RSpec::Matchers.define` will be evaluated in the context
|
226
|
+
# of the singleton class of an instance, and will have the
|
227
|
+
# {RSpec::Matchers::DSL::Macros Macros} methods available.
|
228
|
+
class Matcher
|
229
|
+
# Provides default implementations for the matcher protocol methods.
|
230
|
+
include DefaultImplementations
|
324
231
|
|
325
|
-
|
326
|
-
|
327
|
-
# declared in the block eval'd by instance_exec in the block to which we
|
328
|
-
# are yielding here are scoped private. This is NOT the case for Ruby
|
329
|
-
# 1.8.7 or 1.9.
|
330
|
-
#
|
331
|
-
# Also, due some crazy scoping that I don't understand, these methods
|
332
|
-
# are actually available in the specs (something about the matcher being
|
333
|
-
# defined in the scope of RSpec::Matchers or within an example), so not
|
334
|
-
# doing the following will not cause specs to fail, but they *will*
|
335
|
-
# cause features to fail and that will make users unhappy. So don't.
|
336
|
-
orig_private_methods = private_methods
|
337
|
-
yield
|
338
|
-
(private_methods - orig_private_methods).each {|m| singleton_class.__send__ :public, m}
|
339
|
-
end
|
232
|
+
# Allows expectation expressions to be used in the match block.
|
233
|
+
include RSpec::Matchers
|
340
234
|
|
341
|
-
|
342
|
-
|
343
|
-
end
|
235
|
+
# Converts matcher name and expected args to an English expresion.
|
236
|
+
include RSpec::Matchers::Pretty
|
344
237
|
|
345
|
-
|
346
|
-
|
347
|
-
end
|
238
|
+
# Makes the macro methods available to an `RSpec::Matchers.define` block.
|
239
|
+
extend Macros
|
348
240
|
|
349
|
-
|
350
|
-
|
351
|
-
@messages[key].arity == 1 ? @messages[key].call(@actual) : @messages[key].call
|
352
|
-
else
|
353
|
-
__send__("default_#{key}")
|
354
|
-
end
|
355
|
-
end
|
241
|
+
attr_reader :expected, :actual, :rescued_exception
|
242
|
+
attr_accessor :matcher_execution_context
|
356
243
|
|
357
|
-
|
358
|
-
|
359
|
-
|
244
|
+
# @api private
|
245
|
+
def initialize(name, declarations, *expected)
|
246
|
+
@name = name
|
247
|
+
@actual = nil
|
248
|
+
@expected = expected
|
360
249
|
|
361
|
-
|
362
|
-
|
250
|
+
class << self
|
251
|
+
# See `Macros#define_user_override` above, for an explanation.
|
252
|
+
include(@user_method_defs = Module.new)
|
253
|
+
self
|
254
|
+
end.class_exec(*expected, &declarations)
|
363
255
|
end
|
364
256
|
|
365
|
-
|
366
|
-
|
257
|
+
# Adds the name (rather than a cryptic hex number)
|
258
|
+
# so we can identify an instance of
|
259
|
+
# the matcher in error messages (e.g. for `NoMethodError`)
|
260
|
+
def inspect
|
261
|
+
"#<#{self.class.name} #{name}>"
|
367
262
|
end
|
368
263
|
|
369
|
-
|
370
|
-
|
371
|
-
|
264
|
+
if RUBY_VERSION.to_f >= 1.9
|
265
|
+
# Indicates that this matcher responds to messages
|
266
|
+
# from the `matcher_execution_context` as well.
|
267
|
+
# Also, supports getting a method object for such methods.
|
268
|
+
def respond_to_missing?(method, include_private=false)
|
269
|
+
super || matcher_execution_context.respond_to?(method, include_private)
|
372
270
|
end
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
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
|
-
)
|
271
|
+
else # for 1.8.7
|
272
|
+
# Indicates that this matcher responds to messages
|
273
|
+
# from the `matcher_execution_context` as well.
|
274
|
+
def respond_to?(method, include_private=false)
|
275
|
+
super || matcher_execution_context.respond_to?(method, include_private)
|
392
276
|
end
|
393
277
|
end
|
394
278
|
|
395
|
-
|
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)
|
279
|
+
private
|
401
280
|
|
402
|
-
|
403
|
-
|
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
|
281
|
+
def actual_arg_for(block)
|
282
|
+
block.arity.zero? ? [] : [@actual]
|
412
283
|
end
|
413
284
|
|
414
|
-
|
415
|
-
|
416
|
-
|
285
|
+
# Takes care of forwarding unhandled messages to the
|
286
|
+
# `matcher_execution_context` (typically the current
|
287
|
+
# running `RSpec::Core::Example`). This is needed by
|
288
|
+
# rspec-rails so that it can define matchers that wrap
|
289
|
+
# Rails' test helper methods, but it's also a useful
|
290
|
+
# feature in its own right.
|
291
|
+
def method_missing(method, *args, &block)
|
292
|
+
if matcher_execution_context.respond_to?(method)
|
293
|
+
matcher_execution_context.__send__ method, *args, &block
|
294
|
+
else
|
295
|
+
super(method, *args, &block)
|
296
|
+
end
|
417
297
|
end
|
418
298
|
end
|
419
299
|
end
|