rspec-expectations 3.0.0.beta1 → 3.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +2 -2
- data/.yardopts +1 -0
- data/Changelog.md +138 -0
- data/README.md +75 -8
- data/features/README.md +2 -2
- data/features/built_in_matchers/README.md +12 -9
- data/features/built_in_matchers/comparisons.feature +2 -2
- data/features/built_in_matchers/contain_exactly.feature +46 -0
- data/features/built_in_matchers/expect_change.feature +2 -2
- data/features/built_in_matchers/include.feature +0 -48
- data/features/built_in_matchers/output.feature +70 -0
- data/features/composing_matchers.feature +250 -0
- data/features/compound_expectations.feature +45 -0
- data/features/custom_matchers/access_running_example.feature +1 -1
- data/features/custom_matchers/define_matcher.feature +6 -6
- data/features/custom_matchers/define_matcher_outside_rspec.feature +4 -8
- data/features/test_frameworks/{test_unit.feature → minitest.feature} +11 -11
- data/lib/rspec/expectations.rb +31 -42
- data/lib/rspec/expectations/diff_presenter.rb +141 -0
- data/lib/rspec/expectations/differ.rb +22 -132
- data/lib/rspec/expectations/encoded_string.rb +56 -0
- data/lib/rspec/expectations/expectation_target.rb +0 -30
- data/lib/rspec/expectations/fail_with.rb +2 -2
- data/lib/rspec/expectations/handler.rb +128 -31
- data/lib/rspec/expectations/minitest_integration.rb +16 -0
- data/lib/rspec/expectations/syntax.rb +4 -58
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +298 -60
- data/lib/rspec/matchers/aliased_matcher.rb +35 -0
- data/lib/rspec/matchers/built_in.rb +37 -33
- data/lib/rspec/matchers/built_in/base_matcher.rb +25 -15
- data/lib/rspec/matchers/built_in/be.rb +23 -31
- data/lib/rspec/matchers/built_in/be_between.rb +55 -0
- data/lib/rspec/matchers/built_in/be_within.rb +15 -11
- data/lib/rspec/matchers/built_in/change.rb +198 -81
- data/lib/rspec/matchers/built_in/compound.rb +106 -0
- data/lib/rspec/matchers/built_in/contain_exactly.rb +245 -0
- data/lib/rspec/matchers/built_in/eq.rb +43 -4
- data/lib/rspec/matchers/built_in/eql.rb +2 -2
- data/lib/rspec/matchers/built_in/equal.rb +35 -18
- data/lib/rspec/matchers/built_in/has.rb +16 -15
- data/lib/rspec/matchers/built_in/include.rb +45 -23
- data/lib/rspec/matchers/built_in/match.rb +6 -3
- data/lib/rspec/matchers/built_in/operators.rb +103 -0
- data/lib/rspec/matchers/built_in/output.rb +108 -0
- data/lib/rspec/matchers/built_in/raise_error.rb +9 -15
- data/lib/rspec/matchers/built_in/respond_to.rb +5 -4
- data/lib/rspec/matchers/built_in/satisfy.rb +4 -3
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +37 -16
- data/lib/rspec/matchers/built_in/throw_symbol.rb +6 -5
- data/lib/rspec/matchers/built_in/yield.rb +31 -29
- data/lib/rspec/matchers/composable.rb +138 -0
- data/lib/rspec/matchers/dsl.rb +330 -0
- data/lib/rspec/matchers/generated_descriptions.rb +6 -6
- data/lib/rspec/matchers/matcher_delegator.rb +33 -0
- data/lib/rspec/matchers/pretty.rb +13 -2
- data/spec/rspec/expectations/{differ_spec.rb → diff_presenter_spec.rb} +56 -36
- data/spec/rspec/expectations/encoded_string_spec.rb +74 -0
- data/spec/rspec/expectations/extensions/kernel_spec.rb +11 -11
- data/spec/rspec/expectations/fail_with_spec.rb +8 -8
- data/spec/rspec/expectations/handler_spec.rb +27 -49
- data/spec/rspec/expectations/minitest_integration_spec.rb +27 -0
- data/spec/rspec/expectations/syntax_spec.rb +17 -67
- data/spec/rspec/expectations_spec.rb +7 -52
- data/spec/rspec/matchers/aliased_matcher_spec.rb +48 -0
- data/spec/rspec/matchers/aliases_spec.rb +449 -0
- data/spec/rspec/matchers/{base_matcher_spec.rb → built_in/base_matcher_spec.rb} +24 -3
- data/spec/rspec/matchers/built_in/be_between_spec.rb +159 -0
- data/spec/rspec/matchers/{be_instance_of_spec.rb → built_in/be_instance_of_spec.rb} +0 -0
- data/spec/rspec/matchers/{be_kind_of_spec.rb → built_in/be_kind_of_spec.rb} +0 -0
- data/spec/rspec/matchers/{be_spec.rb → built_in/be_spec.rb} +76 -32
- data/spec/rspec/matchers/{be_within_spec.rb → built_in/be_within_spec.rb} +6 -2
- data/spec/rspec/matchers/{change_spec.rb → built_in/change_spec.rb} +310 -69
- data/spec/rspec/matchers/built_in/compound_spec.rb +292 -0
- data/spec/rspec/matchers/built_in/contain_exactly_spec.rb +441 -0
- data/spec/rspec/matchers/{cover_spec.rb → built_in/cover_spec.rb} +0 -0
- data/spec/rspec/matchers/built_in/eq_spec.rb +156 -0
- data/spec/rspec/matchers/{eql_spec.rb → built_in/eql_spec.rb} +2 -2
- data/spec/rspec/matchers/built_in/equal_spec.rb +106 -0
- data/spec/rspec/matchers/{exist_spec.rb → built_in/exist_spec.rb} +1 -1
- data/spec/rspec/matchers/{has_spec.rb → built_in/has_spec.rb} +39 -0
- data/spec/rspec/matchers/{include_spec.rb → built_in/include_spec.rb} +118 -109
- data/spec/rspec/matchers/{match_spec.rb → built_in/match_spec.rb} +30 -2
- data/spec/rspec/matchers/{operator_matcher_spec.rb → built_in/operators_spec.rb} +26 -26
- data/spec/rspec/matchers/built_in/output_spec.rb +165 -0
- data/spec/rspec/matchers/{raise_error_spec.rb → built_in/raise_error_spec.rb} +81 -11
- data/spec/rspec/matchers/{respond_to_spec.rb → built_in/respond_to_spec.rb} +0 -0
- data/spec/rspec/matchers/{satisfy_spec.rb → built_in/satisfy_spec.rb} +0 -0
- data/spec/rspec/matchers/{start_with_end_with_spec.rb → built_in/start_and_end_with_spec.rb} +82 -15
- data/spec/rspec/matchers/{throw_symbol_spec.rb → built_in/throw_symbol_spec.rb} +29 -10
- data/spec/rspec/matchers/{yield_spec.rb → built_in/yield_spec.rb} +90 -0
- data/spec/rspec/matchers/configuration_spec.rb +7 -39
- data/spec/rspec/matchers/description_generation_spec.rb +22 -6
- data/spec/rspec/matchers/dsl_spec.rb +838 -0
- data/spec/rspec/matchers/legacy_spec.rb +101 -0
- data/spec/rspec/matchers_spec.rb +74 -0
- data/spec/spec_helper.rb +35 -21
- data/spec/support/shared_examples.rb +26 -4
- metadata +172 -116
- metadata.gz.sig +3 -4
- checksums.yaml +0 -15
- checksums.yaml.gz.sig +0 -0
- data/features/built_in_matchers/match_array.feature +0 -37
- data/lib/rspec/expectations/errors.rb +0 -9
- data/lib/rspec/expectations/extensions.rb +0 -1
- data/lib/rspec/expectations/extensions/object.rb +0 -29
- data/lib/rspec/matchers/built_in/match_array.rb +0 -51
- data/lib/rspec/matchers/compatibility.rb +0 -14
- data/lib/rspec/matchers/matcher.rb +0 -301
- data/lib/rspec/matchers/method_missing.rb +0 -12
- data/lib/rspec/matchers/operator_matcher.rb +0 -99
- data/lib/rspec/matchers/test_unit_integration.rb +0 -11
- data/spec/rspec/matchers/eq_spec.rb +0 -60
- data/spec/rspec/matchers/equal_spec.rb +0 -78
- data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
- data/spec/rspec/matchers/match_array_spec.rb +0 -194
- data/spec/rspec/matchers/matcher_spec.rb +0 -706
- data/spec/rspec/matchers/matchers_spec.rb +0 -36
- data/spec/rspec/matchers/method_missing_spec.rb +0 -28
- data/spec/support/classes.rb +0 -56
- data/spec/support/in_sub_process.rb +0 -37
- data/spec/support/ruby_version.rb +0 -10
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class RespondTo
|
5
|
+
include Composable
|
6
|
+
|
5
7
|
def initialize(*names)
|
6
8
|
@names = names
|
7
9
|
@expected_arity = nil
|
@@ -10,18 +12,17 @@ module RSpec
|
|
10
12
|
def matches?(actual)
|
11
13
|
find_failing_method_names(actual, :reject).empty?
|
12
14
|
end
|
13
|
-
alias == matches?
|
14
15
|
|
15
16
|
def does_not_match?(actual)
|
16
17
|
find_failing_method_names(actual, :select).empty?
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
+
def failure_message
|
20
21
|
"expected #{@actual.inspect} to respond to #{@failing_method_names.collect {|name| name.inspect }.join(', ')}#{with_arity}"
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
-
|
24
|
+
def failure_message_when_negated
|
25
|
+
failure_message.sub(/to respond to/, 'not to respond to')
|
25
26
|
end
|
26
27
|
|
27
28
|
def description
|
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class Satisfy
|
5
|
+
include Composable
|
6
|
+
|
5
7
|
def initialize(&block)
|
6
8
|
@block = block
|
7
9
|
end
|
@@ -11,13 +13,12 @@ module RSpec
|
|
11
13
|
@actual = actual
|
12
14
|
@block.call(actual)
|
13
15
|
end
|
14
|
-
alias == matches?
|
15
16
|
|
16
|
-
def
|
17
|
+
def failure_message
|
17
18
|
"expected #{@actual} to satisfy block"
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
+
def failure_message_when_negated
|
21
22
|
"expected #{@actual} not to satisfy block"
|
22
23
|
end
|
23
24
|
|
@@ -3,44 +3,65 @@ module RSpec
|
|
3
3
|
module BuiltIn
|
4
4
|
class StartAndEndWith < BaseMatcher
|
5
5
|
def initialize(*expected)
|
6
|
+
@actual_does_not_have_ordered_elements = false
|
6
7
|
@expected = expected.length == 1 ? expected.first : expected
|
7
8
|
end
|
8
9
|
|
9
|
-
def
|
10
|
-
|
10
|
+
def match(expected, actual)
|
11
|
+
return false unless actual.respond_to?(:[])
|
12
|
+
|
11
13
|
begin
|
12
|
-
|
14
|
+
return subset_matches? if expected.respond_to?(:length)
|
15
|
+
element_matches?
|
13
16
|
rescue ArgumentError
|
14
|
-
|
17
|
+
@actual_does_not_have_ordered_elements = true
|
18
|
+
return false
|
15
19
|
end
|
16
20
|
end
|
17
21
|
|
18
|
-
def
|
19
|
-
|
22
|
+
def failure_message
|
23
|
+
super.tap do |msg|
|
24
|
+
if @actual_does_not_have_ordered_elements
|
25
|
+
msg << ", but it does not have ordered elements"
|
26
|
+
elsif !actual.respond_to?(:[])
|
27
|
+
msg << ", but it cannot be indexed using #[]"
|
28
|
+
end
|
29
|
+
end
|
20
30
|
end
|
21
31
|
|
22
|
-
def
|
23
|
-
|
32
|
+
def description
|
33
|
+
return super unless Hash === expected
|
34
|
+
"#{name_to_sentence} #{surface_descriptions_in(expected).inspect}"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def actual_is_unordered
|
40
|
+
ArgumentError.new("#{actual.inspect} does not have ordered elements")
|
24
41
|
end
|
25
42
|
end
|
26
43
|
|
27
44
|
class StartWith < StartAndEndWith
|
28
|
-
|
29
|
-
|
45
|
+
private
|
46
|
+
|
47
|
+
def subset_matches?
|
48
|
+
values_match?(expected, actual[0, expected.length])
|
30
49
|
end
|
31
50
|
|
32
|
-
def element_matches?
|
33
|
-
|
51
|
+
def element_matches?
|
52
|
+
values_match?(expected, actual[0])
|
34
53
|
end
|
35
54
|
end
|
36
55
|
|
37
56
|
class EndWith < StartAndEndWith
|
38
|
-
|
39
|
-
|
57
|
+
private
|
58
|
+
|
59
|
+
def subset_matches?
|
60
|
+
values_match?(expected, actual[-expected.length, expected.length])
|
40
61
|
end
|
41
62
|
|
42
|
-
def element_matches?
|
43
|
-
actual[-1]
|
63
|
+
def element_matches?
|
64
|
+
values_match?(expected, actual[-1])
|
44
65
|
end
|
45
66
|
end
|
46
67
|
end
|
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class ThrowSymbol
|
5
|
+
include Composable
|
6
|
+
|
5
7
|
def initialize(expected_symbol = nil, expected_arg=nil)
|
6
8
|
@expected_symbol = expected_symbol
|
7
9
|
@expected_arg = expected_arg
|
@@ -45,19 +47,18 @@ module RSpec
|
|
45
47
|
if @expected_arg.nil?
|
46
48
|
return @caught_symbol == @expected_symbol
|
47
49
|
else
|
48
|
-
return (@caught_symbol == @expected_symbol)
|
50
|
+
return (@caught_symbol == @expected_symbol) && values_match?(@expected_arg, @caught_arg)
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
54
|
-
alias == matches?
|
55
56
|
|
56
|
-
def
|
57
|
+
def failure_message
|
57
58
|
"expected #{expected} to be thrown, got #{caught}"
|
58
59
|
end
|
59
60
|
|
60
|
-
def
|
61
|
+
def failure_message_when_negated
|
61
62
|
"expected #{expected('no Symbol')}#{' not' if @expected_symbol} to be thrown, got #{caught}"
|
62
63
|
end
|
63
64
|
|
@@ -79,7 +80,7 @@ module RSpec
|
|
79
80
|
symbol_description = symbol.is_a?(String) ? symbol : symbol.inspect
|
80
81
|
|
81
82
|
arg_description = if arg
|
82
|
-
" with #{arg
|
83
|
+
" with #{description_of arg}"
|
83
84
|
elsif @expected_arg && @caught_symbol == @expected_symbol
|
84
85
|
" with no argument"
|
85
86
|
else
|
@@ -110,13 +110,13 @@ module RSpec
|
|
110
110
|
self
|
111
111
|
end
|
112
112
|
|
113
|
-
def
|
113
|
+
def failure_message
|
114
114
|
'expected given block to yield control'.tap do |failure_message|
|
115
115
|
failure_message << relativity_failure_message
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
def
|
119
|
+
def failure_message_when_negated
|
120
120
|
'expected given block not to yield control'.tap do |failure_message|
|
121
121
|
failure_message << relativity_failure_message
|
122
122
|
end
|
@@ -162,11 +162,11 @@ module RSpec
|
|
162
162
|
@probe.yielded_once?(:yield_with_no_args) && @probe.single_yield_args.empty?
|
163
163
|
end
|
164
164
|
|
165
|
-
def
|
165
|
+
def failure_message
|
166
166
|
"expected given block to yield with no arguments, but #{failure_reason}"
|
167
167
|
end
|
168
168
|
|
169
|
-
def
|
169
|
+
def failure_message_when_negated
|
170
170
|
"expected given block not to yield with no arguments, but did"
|
171
171
|
end
|
172
172
|
|
@@ -182,6 +182,8 @@ module RSpec
|
|
182
182
|
end
|
183
183
|
|
184
184
|
class YieldWithArgs
|
185
|
+
include Composable
|
186
|
+
|
185
187
|
def initialize(*args)
|
186
188
|
@expected = args
|
187
189
|
end
|
@@ -191,19 +193,18 @@ module RSpec
|
|
191
193
|
@actual = @probe.single_yield_args
|
192
194
|
@probe.yielded_once?(:yield_with_args) && args_match?
|
193
195
|
end
|
194
|
-
alias == matches?
|
195
196
|
|
196
|
-
def
|
197
|
+
def failure_message
|
197
198
|
"expected given block to yield with arguments, but #{positive_failure_reason}"
|
198
199
|
end
|
199
200
|
|
200
|
-
def
|
201
|
+
def failure_message_when_negated
|
201
202
|
"expected given block not to yield with arguments, but #{negative_failure_reason}"
|
202
203
|
end
|
203
204
|
|
204
205
|
def description
|
205
206
|
desc = "yield with args"
|
206
|
-
desc << "(
|
207
|
+
desc << "(#{expected_arg_description})" unless @expected.empty?
|
207
208
|
desc
|
208
209
|
end
|
209
210
|
|
@@ -217,11 +218,15 @@ module RSpec
|
|
217
218
|
end
|
218
219
|
end
|
219
220
|
|
221
|
+
def expected_arg_description
|
222
|
+
@expected.map { |e| description_of e }.join(", ")
|
223
|
+
end
|
224
|
+
|
220
225
|
def negative_failure_reason
|
221
226
|
if all_args_match?
|
222
227
|
"yielded with expected arguments" +
|
223
|
-
"\nexpected not: #{@expected.inspect}" +
|
224
|
-
"\n got: #{@actual.inspect}
|
228
|
+
"\nexpected not: #{surface_descriptions_in(@expected).inspect}" +
|
229
|
+
"\n got: #{@actual.inspect}"
|
225
230
|
else
|
226
231
|
"did"
|
227
232
|
end
|
@@ -235,23 +240,21 @@ module RSpec
|
|
235
240
|
|
236
241
|
unless match = all_args_match?
|
237
242
|
@positive_args_failure = "yielded with unexpected arguments" +
|
238
|
-
"\nexpected: #{@expected.inspect}" +
|
239
|
-
"\n got: #{@actual.inspect}
|
243
|
+
"\nexpected: #{surface_descriptions_in(@expected).inspect}" +
|
244
|
+
"\n got: #{@actual.inspect}"
|
240
245
|
end
|
241
246
|
|
242
247
|
match
|
243
248
|
end
|
244
249
|
|
245
250
|
def all_args_match?
|
246
|
-
|
247
|
-
|
248
|
-
@expected.zip(@actual).all? do |expected, actual|
|
249
|
-
expected === actual || actual == expected
|
250
|
-
end
|
251
|
+
values_match?(@expected, @actual)
|
251
252
|
end
|
252
253
|
end
|
253
254
|
|
254
255
|
class YieldSuccessiveArgs
|
256
|
+
include Composable
|
257
|
+
|
255
258
|
def initialize(*args)
|
256
259
|
@expected = args
|
257
260
|
end
|
@@ -261,34 +264,33 @@ module RSpec
|
|
261
264
|
@actual = @probe.successive_yield_args
|
262
265
|
args_match?
|
263
266
|
end
|
264
|
-
alias == matches?
|
265
267
|
|
266
|
-
def
|
268
|
+
def failure_message
|
267
269
|
"expected given block to yield successively with arguments, but yielded with unexpected arguments" +
|
268
|
-
"\nexpected: #{@expected.inspect}" +
|
269
|
-
"\n got: #{@actual.inspect}
|
270
|
+
"\nexpected: #{surface_descriptions_in(@expected).inspect}" +
|
271
|
+
"\n got: #{@actual.inspect}"
|
270
272
|
end
|
271
273
|
|
272
|
-
def
|
274
|
+
def failure_message_when_negated
|
273
275
|
"expected given block not to yield successively with arguments, but yielded with expected arguments" +
|
274
|
-
"\nexpected not: #{@expected.inspect}" +
|
275
|
-
"\n got: #{@actual.inspect}
|
276
|
+
"\nexpected not: #{surface_descriptions_in(@expected).inspect}" +
|
277
|
+
"\n got: #{@actual.inspect}"
|
276
278
|
end
|
277
279
|
|
278
280
|
def description
|
279
281
|
desc = "yield successive args"
|
280
|
-
desc << "(
|
282
|
+
desc << "(#{expected_arg_description})"
|
281
283
|
desc
|
282
284
|
end
|
283
285
|
|
284
286
|
private
|
285
287
|
|
286
288
|
def args_match?
|
287
|
-
|
289
|
+
values_match?(@expected, @actual)
|
290
|
+
end
|
288
291
|
|
289
|
-
|
290
|
-
|
291
|
-
end
|
292
|
+
def expected_arg_description
|
293
|
+
@expected.map { |e| description_of e }.join(", ")
|
292
294
|
end
|
293
295
|
end
|
294
296
|
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'rspec/support/fuzzy_matcher'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Matchers
|
5
|
+
# Mixin designed to support the composable matcher features
|
6
|
+
# of RSpec 3+. Mix it into your custom matcher classes to
|
7
|
+
# allow them to be used in a composable fashion.
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
module Composable
|
11
|
+
# Creates a compound `and` expectation. The matcher will
|
12
|
+
# only pass if both sub-matchers pass.
|
13
|
+
# This can be chained together to form an arbitrarily long
|
14
|
+
# chain of matchers.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# expect(alphabet).to start_with("a").and end_with("z")
|
18
|
+
#
|
19
|
+
# @note The negative form (`expect(...).not_to matcher.and other`)
|
20
|
+
# is not supported at this time.
|
21
|
+
def and(matcher)
|
22
|
+
BuiltIn::Compound::And.new self, matcher
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a compound `or` expectation. The matcher will
|
26
|
+
# pass if either sub-matcher passes.
|
27
|
+
# This can be chained together to form an arbitrarily long
|
28
|
+
# chain of matchers.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# expect(stoplight.color).to eq("red").or eq("green").or eq("yellow")
|
32
|
+
#
|
33
|
+
# @note The negative form (`expect(...).not_to matcher.or other`)
|
34
|
+
# is not supported at this time.
|
35
|
+
def or(matcher)
|
36
|
+
BuiltIn::Compound::Or.new self, matcher
|
37
|
+
end
|
38
|
+
|
39
|
+
# Delegates to `#matches?`. Allows matchers to be used in composable
|
40
|
+
# fashion and also supports using matchers in case statements.
|
41
|
+
def ===(value)
|
42
|
+
matches?(value)
|
43
|
+
end
|
44
|
+
|
45
|
+
private unless defined?(::YARD)
|
46
|
+
|
47
|
+
# This provides a generic way to fuzzy-match an expected value against
|
48
|
+
# an actual value. It understands nested data structures (e.g. hashes
|
49
|
+
# and arrays) and is able to match against a matcher being used as
|
50
|
+
# the expected value or within the expected value at any level of
|
51
|
+
# nesting.
|
52
|
+
#
|
53
|
+
# Within a custom matcher you are encouraged to use this whenever your
|
54
|
+
# matcher needs to match two values, unless it needs more precise semantics.
|
55
|
+
# For example, the `eq` matcher _does not_ use this as it is meant to
|
56
|
+
# use `==` (and only `==`) for matching.
|
57
|
+
#
|
58
|
+
# @param expected [Object] what is expected
|
59
|
+
# @param actual [Object] the actual value
|
60
|
+
#
|
61
|
+
# @public
|
62
|
+
def values_match?(expected, actual)
|
63
|
+
Support::FuzzyMatcher.values_match?(expected, actual)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the description of the given object in a way that is
|
67
|
+
# aware of composed matchers. If the object is a matcher with
|
68
|
+
# a `description` method, returns the description; otherwise
|
69
|
+
# returns `object.inspect`.
|
70
|
+
#
|
71
|
+
# You are encouraged to use this in your custom matcher's
|
72
|
+
# `description`, `failure_message` or
|
73
|
+
# `failure_message_when_negated` implementation if you are
|
74
|
+
# supporting matcher arguments.
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
def description_of(object)
|
78
|
+
return object.description if Matchers.is_a_describable_matcher?(object)
|
79
|
+
object.inspect
|
80
|
+
end
|
81
|
+
|
82
|
+
# Transforms the given data structue (typically a hash or array)
|
83
|
+
# into a new data structure that, when `#inspect` is called on it,
|
84
|
+
# will provide descriptions of any contained matchers rather than
|
85
|
+
# the normal `#inspect` output.
|
86
|
+
#
|
87
|
+
# You are encouraged to use this in your custom matcher's
|
88
|
+
# `description`, `failure_message` or
|
89
|
+
# `failure_message_when_negated` implementation if you are
|
90
|
+
# supporting any arguments which may be a data structure
|
91
|
+
# containing matchers.
|
92
|
+
#
|
93
|
+
# @api public
|
94
|
+
def surface_descriptions_in(item)
|
95
|
+
if Matchers.is_a_describable_matcher?(item)
|
96
|
+
DescribableItem.new(item)
|
97
|
+
elsif Hash === item
|
98
|
+
Hash[ surface_descriptions_in(item.to_a) ]
|
99
|
+
elsif enumerable?(item)
|
100
|
+
item.map { |subitem| surface_descriptions_in(subitem) }
|
101
|
+
else
|
102
|
+
item
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if String.ancestors.include?(Enumerable) # 1.8.7
|
107
|
+
# Strings are not enumerable on 1.9, and on 1.8 they are an infinitely
|
108
|
+
# nested enumerable: since ruby lacks a character class, it yields
|
109
|
+
# 1-character strings, which are themselves enumerable, composed of a
|
110
|
+
# a single 1-character string, which is an enumerable, etc.
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
def enumerable?(item)
|
114
|
+
return false if String === item
|
115
|
+
Enumerable === item
|
116
|
+
end
|
117
|
+
else
|
118
|
+
# @api private
|
119
|
+
def enumerable?(item)
|
120
|
+
Enumerable === item
|
121
|
+
end
|
122
|
+
end
|
123
|
+
module_function :surface_descriptions_in, :enumerable? unless defined?(::YARD)
|
124
|
+
|
125
|
+
# Wraps an item in order to surface its `description` via `inspect`.
|
126
|
+
# @api private
|
127
|
+
DescribableItem = Struct.new(:item) do
|
128
|
+
def inspect
|
129
|
+
"(#{item.description})"
|
130
|
+
end
|
131
|
+
|
132
|
+
def pretty_print(pp)
|
133
|
+
pp.text "(#{item.description})"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|