rspec-expectations 2.99.0.beta2 → 2.99.0.rc1
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 +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)
|