rspec-expectations 3.0.4 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +32 -1
- data/lib/rspec/expectations/configuration.rb +12 -0
- data/lib/rspec/expectations/handler.rb +9 -3
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +66 -20
- data/lib/rspec/matchers/aliased_matcher.rb +46 -2
- data/lib/rspec/matchers/built_in.rb +1 -0
- data/lib/rspec/matchers/built_in/all.rb +10 -0
- data/lib/rspec/matchers/built_in/base_matcher.rb +5 -0
- data/lib/rspec/matchers/built_in/be_within.rb +1 -8
- data/lib/rspec/matchers/built_in/change.rb +3 -8
- data/lib/rspec/matchers/built_in/compound.rb +150 -11
- data/lib/rspec/matchers/built_in/contain_exactly.rb +1 -1
- data/lib/rspec/matchers/built_in/has.rb +6 -9
- data/lib/rspec/matchers/built_in/have_attributes.rb +84 -0
- data/lib/rspec/matchers/built_in/output.rb +3 -1
- data/lib/rspec/matchers/built_in/raise_error.rb +6 -0
- data/lib/rspec/matchers/built_in/respond_to.rb +2 -9
- data/lib/rspec/matchers/built_in/satisfy.rb +1 -8
- data/lib/rspec/matchers/built_in/throw_symbol.rb +4 -0
- data/lib/rspec/matchers/built_in/yield.rb +29 -11
- data/lib/rspec/matchers/dsl.rb +24 -4
- data/lib/rspec/matchers/matcher_delegator.rb +1 -4
- data/lib/rspec/matchers/matcher_protocol.rb +99 -0
- metadata +7 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d67d8e69dfda8789a69783ab55ae688851cd637
|
4
|
+
data.tar.gz: b7eeed6108dc7341331d64f62e1c057c08545c9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b49a1de8f140c99b2bf9fda0af0382c6381f44dfb568626720297c5cd83a9eff033facefa2ff4f312c81c73e9257499bbee9cfe1010f527763d241c8155e2f5
|
7
|
+
data.tar.gz: c054e2dee14f838f498918c7b3964381c633fa7d8552242fc16d3d267300cc071aad83e6ef3eedbedda9a9de63553bc27d0d15099fe93c6221eb087b9e02748e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
### 3.1.0 / 2014-09-04
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.4...v3.1.0)
|
3
|
+
|
4
|
+
Enhancements:
|
5
|
+
|
6
|
+
* Add `have_attributes` matcher, that passes if actual's attribute
|
7
|
+
values match the expected attributes hash:
|
8
|
+
`Person = Struct.new(:name, :age)`
|
9
|
+
`person = Person.new("Bob", 32)`
|
10
|
+
`expect(person).to have_attributes(:name => "Bob", :age => 32)`.
|
11
|
+
(Adam Farhi, #571)
|
12
|
+
* Extended compound matcher support to block matchers, for cases like:
|
13
|
+
`expect { ... }.to change { x }.to(3).and change { y }.to(4)`. (Myron
|
14
|
+
Marston, #567)
|
15
|
+
* Include chained methods in custom matcher description and failure message
|
16
|
+
when new `include_chain_clauses_in_custom_matcher_descriptions` config
|
17
|
+
option is enabled. (Dan Oved, #600)
|
18
|
+
* Add `thrice` modifier to `yield_control` matcher as a synonym for
|
19
|
+
`exactly(3).times`. (Dennis Taylor, #615)
|
20
|
+
* Add `RSpec::Matchers.define_negated_matcher`, which defines a negated
|
21
|
+
version of the named matcher. (Adam Farhi, Myron Marston, #618)
|
22
|
+
* Document and support negation of `contain_exactly`/`match_array`.
|
23
|
+
(Jon Rowe, #626).
|
24
|
+
|
25
|
+
Bug Fixes:
|
26
|
+
|
27
|
+
* Rename private `LegacyMacherAdapter` constant to `LegacyMatcherAdapter`
|
28
|
+
to fix typo. (Abdelkader Boudih, #563)
|
29
|
+
* Fix `all` matcher so that it fails properly (rather than raising a
|
30
|
+
`NoMethodError`) when matched against a non-enumerable. (Hao Su, #622)
|
31
|
+
|
1
32
|
### 3.0.4 / 2014-08-14
|
2
33
|
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.0.3...v3.0.4)
|
3
34
|
|
@@ -162,7 +193,7 @@ Enhancements:
|
|
162
193
|
* Define noun-phrase aliases for built-in matchers, which can be
|
163
194
|
used when creating composed matcher expressions that read better
|
164
195
|
and provide better failure messages. (Myron Marston)
|
165
|
-
* Add `RSpec::
|
196
|
+
* Add `RSpec::Matchers.alias_matcher` so users can define their own
|
166
197
|
matcher aliases. The `description` of the matcher will reflect the
|
167
198
|
alternate matcher name. (Myron Marston)
|
168
199
|
* Add explicit `be_between` matcher. `be_between` has worked for a
|
@@ -107,6 +107,18 @@ module RSpec
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
+
# Sets if custom matcher descriptions and failure messages
|
111
|
+
# should include clauses from methods defined using `chain`.
|
112
|
+
# @param value [Boolean]
|
113
|
+
attr_writer :include_chain_clauses_in_custom_matcher_descriptions
|
114
|
+
|
115
|
+
# Indicates whether or not custom matcher descriptions and failure messages
|
116
|
+
# should include clauses from methods defined using `chain`. It is
|
117
|
+
# false by default for backwards compatibility.
|
118
|
+
def include_chain_clauses_in_custom_matcher_descriptions?
|
119
|
+
@include_chain_clauses_in_custom_matcher_descriptions ||= false
|
120
|
+
end
|
121
|
+
|
110
122
|
# @private
|
111
123
|
def reset_syntaxes_to_default
|
112
124
|
self.syntax = [:should, :expect]
|
@@ -17,8 +17,8 @@ module RSpec
|
|
17
17
|
#
|
18
18
|
# @private
|
19
19
|
def self.modern_matcher_from(matcher)
|
20
|
-
|
21
|
-
|
20
|
+
LegacyMatcherAdapter::RSpec2.wrap(matcher) ||
|
21
|
+
LegacyMatcherAdapter::RSpec1.wrap(matcher) || matcher
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.setup(handler, matcher, message)
|
@@ -95,7 +95,7 @@ module RSpec
|
|
95
95
|
# order to present the current protocol.
|
96
96
|
#
|
97
97
|
# @private
|
98
|
-
class
|
98
|
+
class LegacyMatcherAdapter < Matchers::MatcherDelegator
|
99
99
|
def initialize(matcher)
|
100
100
|
super
|
101
101
|
::RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''), :type => "legacy_matcher")
|
@@ -157,5 +157,11 @@ module RSpec
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
end
|
160
|
+
|
161
|
+
# RSpec 3.0 was released with the class name misspelled. For SemVer compatibility,
|
162
|
+
# we will provide this misspelled alias until 4.0.
|
163
|
+
# @deprecated Use LegacyMatcherAdapter instead.
|
164
|
+
# @private
|
165
|
+
LegacyMacherAdapter = LegacyMatcherAdapter
|
160
166
|
end
|
161
167
|
end
|
data/lib/rspec/matchers.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rspec/support'
|
2
|
+
RSpec::Support.require_rspec_support 'matcher_definition'
|
2
3
|
RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relative(f) }
|
3
4
|
|
4
5
|
%w[
|
@@ -15,17 +16,8 @@ RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relat
|
|
15
16
|
# in the `RSpec::Expectations` and `RSpec::Matchers` namespaces.
|
16
17
|
module RSpec
|
17
18
|
# RSpec::Matchers provides a number of useful matchers we use to define
|
18
|
-
# expectations.
|
19
|
-
#
|
20
|
-
# matches?(actual)
|
21
|
-
# failure_message
|
22
|
-
#
|
23
|
-
# These methods are also part of the matcher protocol, but are optional:
|
24
|
-
#
|
25
|
-
# does_not_match?(actual)
|
26
|
-
# failure_message_when_negated
|
27
|
-
# description
|
28
|
-
# supports_block_expectations?
|
19
|
+
# expectations. Any object that implements the [matcher protocol](Matchers/MatcherProtocol)
|
20
|
+
# can be used as a matcher.
|
29
21
|
#
|
30
22
|
# ## Predicates
|
31
23
|
#
|
@@ -226,6 +218,8 @@ module RSpec
|
|
226
218
|
#
|
227
219
|
# @param new_name [Symbol] the new name for the matcher
|
228
220
|
# @param old_name [Symbol] the original name for the matcher
|
221
|
+
# @param options [Hash] options for the aliased matcher
|
222
|
+
# @option options [Class] :klass the ruby class to use as the decorator. (Not normally used).
|
229
223
|
# @yield [String] optional block that, when given is used to define the overriden
|
230
224
|
# description. The yielded arg is the original description. If no block is
|
231
225
|
# provided, a default description override is used based on the old and
|
@@ -249,17 +243,38 @@ module RSpec
|
|
249
243
|
# @!macro [attach] alias_matcher
|
250
244
|
# @!parse
|
251
245
|
# alias $1 $2
|
252
|
-
def self.alias_matcher(new_name, old_name, &description_override)
|
246
|
+
def self.alias_matcher(new_name, old_name, options={}, &description_override)
|
253
247
|
description_override ||= lambda do |old_desc|
|
254
248
|
old_desc.gsub(Pretty.split_words(old_name), Pretty.split_words(new_name))
|
255
249
|
end
|
250
|
+
klass = options.fetch(:klass) { AliasedMatcher }
|
256
251
|
|
257
252
|
define_method(new_name) do |*args, &block|
|
258
253
|
matcher = __send__(old_name, *args, &block)
|
259
|
-
|
254
|
+
klass.new(matcher, description_override)
|
260
255
|
end
|
261
256
|
end
|
262
257
|
|
258
|
+
# Defines a negated matcher. The returned matcher's `description` and `failure_message`
|
259
|
+
# will be overriden to reflect the phrasing of the new name, and the match logic will
|
260
|
+
# be based on the original matcher but negated.
|
261
|
+
#
|
262
|
+
# @param negated_name [Symbol] the name for the negated matcher
|
263
|
+
# @param base_name [Symbol] the name of the original matcher that will be negated
|
264
|
+
# @yield [String] optional block that, when given is used to define the overriden
|
265
|
+
# description. The yielded arg is the original description. If no block is
|
266
|
+
# provided, a default description override is used based on the old and
|
267
|
+
# new names.
|
268
|
+
#
|
269
|
+
# @example
|
270
|
+
#
|
271
|
+
# RSpec::Matchers.define_negated_matcher :a_value_not_between, :a_value_between
|
272
|
+
# a_value_between(3, 5).description # => "a value between 3 and 5"
|
273
|
+
# a_value_not_between(3, 5).description # => "a value not between 3 and 5"
|
274
|
+
def self.define_negated_matcher(negated_name, base_name, &description_override)
|
275
|
+
alias_matcher(negated_name, base_name, :klass => AliasedNegatedMatcher, &description_override)
|
276
|
+
end
|
277
|
+
|
263
278
|
# Passes if actual is truthy (anything but false or nil)
|
264
279
|
def be_truthy
|
265
280
|
BuiltIn::BeTruthy.new
|
@@ -303,7 +318,7 @@ module RSpec
|
|
303
318
|
def be(*args)
|
304
319
|
args.empty? ? Matchers::BuiltIn::Be.new : equal(*args)
|
305
320
|
end
|
306
|
-
alias_matcher :a_value, :be
|
321
|
+
alias_matcher :a_value, :be, :klass => AliasedMatcherWithOperatorSupport
|
307
322
|
|
308
323
|
# passes if target.kind_of?(klass)
|
309
324
|
def be_a(klass)
|
@@ -382,11 +397,14 @@ module RSpec
|
|
382
397
|
# You can chain any of the following off of the end to specify details
|
383
398
|
# about the change:
|
384
399
|
#
|
400
|
+
# * `from`
|
401
|
+
# * `to`
|
402
|
+
#
|
403
|
+
# or any one of:
|
404
|
+
#
|
385
405
|
# * `by`
|
386
406
|
# * `by_at_least`
|
387
407
|
# * `by_at_most`
|
388
|
-
# * `from`
|
389
|
-
# * `to`
|
390
408
|
#
|
391
409
|
# @example
|
392
410
|
#
|
@@ -455,9 +473,6 @@ module RSpec
|
|
455
473
|
# @note This is also available using the `=~` operator with `should`,
|
456
474
|
# but `=~` is not supported with `expect`.
|
457
475
|
#
|
458
|
-
# @note This matcher only supports positive expectations.
|
459
|
-
# `expect(...).not_to contain_exactly(other_array)` is not supported.
|
460
|
-
#
|
461
476
|
# @example
|
462
477
|
#
|
463
478
|
# expect([1, 2, 3]).to contain_exactly(1, 2, 3)
|
@@ -560,6 +575,27 @@ module RSpec
|
|
560
575
|
alias_matcher :an_object_existing, :exist
|
561
576
|
alias_matcher :existing, :exist
|
562
577
|
|
578
|
+
# Passes if actual's attribute values match the expected attributes hash.
|
579
|
+
# This works no matter how you define your attribute readers.
|
580
|
+
#
|
581
|
+
# @example
|
582
|
+
#
|
583
|
+
# Person = Struct.new(:name, :age)
|
584
|
+
# person = Person.new("Bob", 32)
|
585
|
+
#
|
586
|
+
# expect(person).to have_attributes(:name => "Bob", :age => 32)
|
587
|
+
# expect(person).to have_attributes(:name => a_string_starting_with("B"), :age => (a_value > 30) )
|
588
|
+
#
|
589
|
+
# @note It will fail if actual doesn't respond to any of the expected attributes.
|
590
|
+
#
|
591
|
+
# @example
|
592
|
+
#
|
593
|
+
# expect(person).to have_attributes(:color => "red")
|
594
|
+
def have_attributes(expected)
|
595
|
+
BuiltIn::HaveAttributes.new(expected)
|
596
|
+
end
|
597
|
+
alias_matcher :an_object_having_attributes, :have_attributes
|
598
|
+
|
563
599
|
# Passes if actual includes expected. This works for
|
564
600
|
# collections and Strings. You can also pass in multiple args
|
565
601
|
# and it will only pass if all args are found in collection.
|
@@ -906,13 +942,23 @@ module RSpec
|
|
906
942
|
# @api private
|
907
943
|
def self.is_a_matcher?(obj)
|
908
944
|
return true if ::RSpec::Matchers::BuiltIn::BaseMatcher === obj
|
909
|
-
|
945
|
+
begin
|
946
|
+
return false if obj.respond_to?(:i_respond_to_everything_so_im_not_really_a_matcher)
|
947
|
+
rescue NoMethodError
|
948
|
+
# Some objects, like BasicObject, don't implemented standard
|
949
|
+
# reflection methods.
|
950
|
+
return false
|
951
|
+
end
|
910
952
|
return false unless obj.respond_to?(:matches?)
|
911
953
|
|
912
954
|
obj.respond_to?(:failure_message) ||
|
913
955
|
obj.respond_to?(:failure_message_for_should) # support legacy matchers
|
914
956
|
end
|
915
957
|
|
958
|
+
::RSpec::Support.register_matcher_definition do |obj|
|
959
|
+
is_a_matcher?(obj)
|
960
|
+
end
|
961
|
+
|
916
962
|
# @api private
|
917
963
|
def self.is_a_describable_matcher?(obj)
|
918
964
|
is_a_matcher?(obj) && obj.respond_to?(:description)
|
@@ -29,13 +29,57 @@ module RSpec
|
|
29
29
|
|
30
30
|
# Provides the description of the aliased matcher. Aliased matchers
|
31
31
|
# are designed to behave identically to the original matcher except
|
32
|
-
# for
|
33
|
-
# name.
|
32
|
+
# for the description and failure messages. The description is different
|
33
|
+
# to reflect the aliased name.
|
34
34
|
#
|
35
35
|
# @api private
|
36
36
|
def description
|
37
37
|
@description_block.call(super)
|
38
38
|
end
|
39
|
+
|
40
|
+
# Provides the failure_message of the aliased matcher. Aliased matchers
|
41
|
+
# are designed to behave identically to the original matcher except
|
42
|
+
# for the description and failure messages. The failure_message is different
|
43
|
+
# to reflect the aliased name.
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
def failure_message
|
47
|
+
@description_block.call(super)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Provides the failure_message_when_negated of the aliased matcher. Aliased matchers
|
51
|
+
# are designed to behave identically to the original matcher except
|
52
|
+
# for the description and failure messages. The failure_message_when_negated is different
|
53
|
+
# to reflect the aliased name.
|
54
|
+
#
|
55
|
+
# @api private
|
56
|
+
def failure_message_when_negated
|
57
|
+
@description_block.call(super)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Decorator used for matchers that have special implementations of
|
62
|
+
# operators like `==` and `===`.
|
63
|
+
# @private
|
64
|
+
class AliasedMatcherWithOperatorSupport < AliasedMatcher
|
65
|
+
# We undef these so that they get delegated via `method_missing`.
|
66
|
+
undef ==
|
67
|
+
undef ===
|
68
|
+
end
|
69
|
+
|
70
|
+
# @private
|
71
|
+
class AliasedNegatedMatcher < AliasedMatcher
|
72
|
+
def matches?(*args, &block)
|
73
|
+
if @base_matcher.respond_to?(:does_not_match?)
|
74
|
+
@base_matcher.does_not_match?(*args, &block)
|
75
|
+
else
|
76
|
+
!super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def does_not_match?(*args, &block)
|
81
|
+
@base_matcher.matches?(*args, &block)
|
82
|
+
end
|
39
83
|
end
|
40
84
|
end
|
41
85
|
end
|
@@ -30,6 +30,7 @@ module RSpec
|
|
30
30
|
autoload :Equal, 'rspec/matchers/built_in/equal'
|
31
31
|
autoload :Exist, 'rspec/matchers/built_in/exist'
|
32
32
|
autoload :Has, 'rspec/matchers/built_in/has'
|
33
|
+
autoload :HaveAttributes, 'rspec/matchers/built_in/have_attributes'
|
33
34
|
autoload :Include, 'rspec/matchers/built_in/include'
|
34
35
|
autoload :All, 'rspec/matchers/built_in/all'
|
35
36
|
autoload :Match, 'rspec/matchers/built_in/match'
|
@@ -21,6 +21,10 @@ module RSpec
|
|
21
21
|
# @api private
|
22
22
|
# @return [String]
|
23
23
|
def failure_message
|
24
|
+
unless enumerable?
|
25
|
+
return "#{improve_hash_formatting(super)}, but was not enumerable"
|
26
|
+
end
|
27
|
+
|
24
28
|
all_messages = [improve_hash_formatting(super)]
|
25
29
|
failed_objects.each do |index, matcher_failure_message|
|
26
30
|
all_messages << failure_message_for_item(index, matcher_failure_message)
|
@@ -37,6 +41,8 @@ module RSpec
|
|
37
41
|
private
|
38
42
|
|
39
43
|
def match(_expected, _actual)
|
44
|
+
return false unless enumerable?
|
45
|
+
|
40
46
|
index_failed_objects
|
41
47
|
failed_objects.empty?
|
42
48
|
end
|
@@ -69,6 +75,10 @@ module RSpec
|
|
69
75
|
@matcher = @matcher.clone
|
70
76
|
super
|
71
77
|
end
|
78
|
+
|
79
|
+
def enumerable?
|
80
|
+
Enumerable === @actual
|
81
|
+
end
|
72
82
|
end
|
73
83
|
end
|
74
84
|
end
|
@@ -4,9 +4,7 @@ module RSpec
|
|
4
4
|
# @api private
|
5
5
|
# Provides the implementation for `be_within`.
|
6
6
|
# Not intended to be instantiated directly.
|
7
|
-
class BeWithin
|
8
|
-
include Composable
|
9
|
-
|
7
|
+
class BeWithin < BaseMatcher
|
10
8
|
def initialize(delta)
|
11
9
|
@delta = delta
|
12
10
|
end
|
@@ -55,11 +53,6 @@ module RSpec
|
|
55
53
|
"be within #{@delta}#{@unit} of #{@expected}"
|
56
54
|
end
|
57
55
|
|
58
|
-
# @private
|
59
|
-
def supports_block_expectations?
|
60
|
-
false
|
61
|
-
end
|
62
|
-
|
63
56
|
private
|
64
57
|
|
65
58
|
def numeric?
|
@@ -4,9 +4,7 @@ module RSpec
|
|
4
4
|
# @api private
|
5
5
|
# Provides the implementation for `change`.
|
6
6
|
# Not intended to be instantiated directly.
|
7
|
-
class Change
|
8
|
-
include Composable
|
9
|
-
|
7
|
+
class Change < BaseMatcher
|
10
8
|
# @api public
|
11
9
|
# Specifies the delta of the expected change.
|
12
10
|
def by(expected_delta)
|
@@ -104,9 +102,7 @@ module RSpec
|
|
104
102
|
|
105
103
|
# Used to specify a relative change.
|
106
104
|
# @api private
|
107
|
-
class ChangeRelatively
|
108
|
-
include Composable
|
109
|
-
|
105
|
+
class ChangeRelatively < BaseMatcher
|
110
106
|
def initialize(change_details, expected_delta, relativity, &comparer)
|
111
107
|
@change_details = change_details
|
112
108
|
@expected_delta = expected_delta
|
@@ -152,8 +148,7 @@ module RSpec
|
|
152
148
|
|
153
149
|
# @api private
|
154
150
|
# Base class for specifying a change from and/or to specific values.
|
155
|
-
class SpecificValuesChange
|
156
|
-
include Composable
|
151
|
+
class SpecificValuesChange < BaseMatcher
|
157
152
|
# @private
|
158
153
|
MATCH_ANYTHING = ::Object.ancestors.last
|
159
154
|
|
@@ -14,8 +14,10 @@ module RSpec
|
|
14
14
|
|
15
15
|
# @private
|
16
16
|
def does_not_match?(_actual)
|
17
|
-
raise NotImplementedError, "`expect(...).not_to " \
|
18
|
-
"
|
17
|
+
raise NotImplementedError, "`expect(...).not_to matcher.#{conjunction} matcher` " \
|
18
|
+
"is not supported, since it creates a bit of an ambiguity. Instead, define negated versions " \
|
19
|
+
"of whatever matchers you wish to negate with `RSpec::Matchers.define_negated_matcher` and " \
|
20
|
+
"use `expect(...).to matcher.#{conjunction} matcher`."
|
19
21
|
end
|
20
22
|
|
21
23
|
# @api private
|
@@ -24,6 +26,16 @@ module RSpec
|
|
24
26
|
singleline_message(matcher_1.description, matcher_2.description)
|
25
27
|
end
|
26
28
|
|
29
|
+
def supports_block_expectations?
|
30
|
+
matcher_supports_block_expectations?(matcher_1) &&
|
31
|
+
matcher_supports_block_expectations?(matcher_2)
|
32
|
+
end
|
33
|
+
|
34
|
+
def expects_call_stack_jump?
|
35
|
+
NestedEvaluator.matcher_expects_call_stack_jump?(matcher_1) ||
|
36
|
+
NestedEvaluator.matcher_expects_call_stack_jump?(matcher_2)
|
37
|
+
end
|
38
|
+
|
27
39
|
private
|
28
40
|
|
29
41
|
def initialize_copy(other)
|
@@ -32,6 +44,16 @@ module RSpec
|
|
32
44
|
super
|
33
45
|
end
|
34
46
|
|
47
|
+
def match(_expected, actual)
|
48
|
+
evaluator_klass = if supports_block_expectations? && Proc === actual
|
49
|
+
NestedEvaluator
|
50
|
+
else
|
51
|
+
SequentialEvaluator
|
52
|
+
end
|
53
|
+
|
54
|
+
@evaluator = evaluator_klass.new(actual, matcher_1, matcher_2)
|
55
|
+
end
|
56
|
+
|
35
57
|
def indent_multiline_message(message)
|
36
58
|
message.lines.map do |line|
|
37
59
|
line =~ /\S/ ? ' ' + line : line
|
@@ -65,15 +87,133 @@ module RSpec
|
|
65
87
|
[message_1, conjunction, message_2].join(' ')
|
66
88
|
end
|
67
89
|
|
90
|
+
def matcher_1_matches?
|
91
|
+
@evaluator.matcher_matches?(matcher_1)
|
92
|
+
end
|
93
|
+
|
94
|
+
def matcher_2_matches?
|
95
|
+
@evaluator.matcher_matches?(matcher_2)
|
96
|
+
end
|
97
|
+
|
98
|
+
def matcher_supports_block_expectations?(matcher)
|
99
|
+
matcher.supports_block_expectations?
|
100
|
+
rescue NoMethodError
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
# For value expectations, we can evaluate the matchers sequentially.
|
105
|
+
class SequentialEvaluator
|
106
|
+
def initialize(actual, *)
|
107
|
+
@actual = actual
|
108
|
+
end
|
109
|
+
|
110
|
+
def matcher_matches?(matcher)
|
111
|
+
matcher.matches?(@actual)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Normally, we evaluate the matching sequentially. For an expression like
|
116
|
+
# `expect(x).to foo.and bar`, this becomes:
|
117
|
+
#
|
118
|
+
# expect(x).to foo
|
119
|
+
# expect(x).to bar
|
120
|
+
#
|
121
|
+
# For block expectations, we need to nest them instead, so that
|
122
|
+
# `expect { x }.to foo.and bar` becomes:
|
123
|
+
#
|
124
|
+
# expect {
|
125
|
+
# expect { x }.to foo
|
126
|
+
# }.to bar
|
127
|
+
#
|
128
|
+
# This is necessary so that the `expect` block is only executed once.
|
129
|
+
class NestedEvaluator
|
130
|
+
def initialize(actual, matcher_1, matcher_2)
|
131
|
+
@actual = actual
|
132
|
+
@matcher_1 = matcher_1
|
133
|
+
@matcher_2 = matcher_2
|
134
|
+
@match_results = {}
|
135
|
+
|
136
|
+
inner, outer = order_block_matchers
|
137
|
+
|
138
|
+
@match_results[outer] = outer.matches?(Proc.new do |*args|
|
139
|
+
@match_results[inner] = inner.matches?(inner_matcher_block(args))
|
140
|
+
end)
|
141
|
+
end
|
142
|
+
|
143
|
+
def matcher_matches?(matcher)
|
144
|
+
@match_results.fetch(matcher)
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# Some block matchers (such as `yield_xyz`) pass args to the `expect` block.
|
150
|
+
# When such a matcher is used as the outer matcher, we need to forward the
|
151
|
+
# the args on to the `expect` block.
|
152
|
+
def inner_matcher_block(outer_args)
|
153
|
+
return @actual if outer_args.empty?
|
154
|
+
|
155
|
+
Proc.new do |*inner_args|
|
156
|
+
unless inner_args.empty?
|
157
|
+
raise ArgumentError, "(#{@matcher_1.description}) and " \
|
158
|
+
"(#{@matcher_2.description}) cannot be combined in a compound expectation " \
|
159
|
+
"since both matchers pass arguments to the block."
|
160
|
+
end
|
161
|
+
|
162
|
+
@actual.call(*outer_args)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# For a matcher like `raise_error` or `throw_symbol`, where the block will jump
|
167
|
+
# up the call stack, we need to order things so that it is the inner matcher.
|
168
|
+
# For example, we need it to be this:
|
169
|
+
#
|
170
|
+
# expect {
|
171
|
+
# expect {
|
172
|
+
# x += 1
|
173
|
+
# raise "boom"
|
174
|
+
# }.to raise_error("boom")
|
175
|
+
# }.to change { x }.by(1)
|
176
|
+
#
|
177
|
+
# ...rather than:
|
178
|
+
#
|
179
|
+
# expect {
|
180
|
+
# expect {
|
181
|
+
# x += 1
|
182
|
+
# raise "boom"
|
183
|
+
# }.to change { x }.by(1)
|
184
|
+
# }.to raise_error("boom")
|
185
|
+
#
|
186
|
+
# In the latter case, the after-block logic in the `change` matcher would never
|
187
|
+
# get executed because the `raise "boom"` line would jump to the `rescue` in the
|
188
|
+
# `raise_error` logic, so only the former case will work properly.
|
189
|
+
#
|
190
|
+
# This method figures out which matcher should be the inner matcher and which
|
191
|
+
# should be the outer matcher.
|
192
|
+
def order_block_matchers
|
193
|
+
return @matcher_1, @matcher_2 unless self.class.matcher_expects_call_stack_jump?(@matcher_2)
|
194
|
+
return @matcher_2, @matcher_1 unless self.class.matcher_expects_call_stack_jump?(@matcher_1)
|
195
|
+
|
196
|
+
raise ArgumentError, "(#{@matcher_1.description}) and " \
|
197
|
+
"(#{@matcher_2.description}) cannot be combined in a compound expectation " \
|
198
|
+
"because they both expect a call stack jump."
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.matcher_expects_call_stack_jump?(matcher)
|
202
|
+
matcher.expects_call_stack_jump?
|
203
|
+
rescue NoMethodError
|
204
|
+
false
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
68
208
|
# @api public
|
69
209
|
# Matcher used to represent a compound `and` expectation.
|
70
210
|
class And < self
|
71
211
|
# @api private
|
72
212
|
# @return [String]
|
73
213
|
def failure_message
|
74
|
-
if
|
214
|
+
if matcher_1_matches?
|
75
215
|
matcher_2.failure_message
|
76
|
-
elsif
|
216
|
+
elsif matcher_2_matches?
|
77
217
|
matcher_1.failure_message
|
78
218
|
else
|
79
219
|
compound_failure_message
|
@@ -82,11 +222,9 @@ module RSpec
|
|
82
222
|
|
83
223
|
private
|
84
224
|
|
85
|
-
def match(
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@matcher_1_matches && @matcher_2_matches
|
225
|
+
def match(*)
|
226
|
+
super
|
227
|
+
matcher_1_matches? && matcher_2_matches?
|
90
228
|
end
|
91
229
|
|
92
230
|
def conjunction
|
@@ -105,8 +243,9 @@ module RSpec
|
|
105
243
|
|
106
244
|
private
|
107
245
|
|
108
|
-
def match(
|
109
|
-
|
246
|
+
def match(*)
|
247
|
+
super
|
248
|
+
matcher_1_matches? || matcher_2_matches?
|
110
249
|
end
|
111
250
|
|
112
251
|
def conjunction
|
@@ -23,7 +23,7 @@ module RSpec
|
|
23
23
|
# @api private
|
24
24
|
# @return [String]
|
25
25
|
def failure_message_when_negated
|
26
|
-
"
|
26
|
+
"expected #{actual.inspect} not to contain exactly#{to_sentence(surface_descriptions_in expected)}"
|
27
27
|
end
|
28
28
|
|
29
29
|
# @api private
|
@@ -4,9 +4,7 @@ module RSpec
|
|
4
4
|
# @api private
|
5
5
|
# Provides the implementation for `has_<predicate>`.
|
6
6
|
# Not intended to be instantiated directly.
|
7
|
-
class Has
|
8
|
-
include Composable
|
9
|
-
|
7
|
+
class Has < BaseMatcher
|
10
8
|
def initialize(method_name, *args, &block)
|
11
9
|
@method_name, @args, @block = method_name, args, block
|
12
10
|
end
|
@@ -43,11 +41,6 @@ module RSpec
|
|
43
41
|
[method_description, args_description].compact.join(' ')
|
44
42
|
end
|
45
43
|
|
46
|
-
# @private
|
47
|
-
def supports_block_expectations?
|
48
|
-
false
|
49
|
-
end
|
50
|
-
|
51
44
|
private
|
52
45
|
|
53
46
|
def predicate_accessible?
|
@@ -74,7 +67,11 @@ module RSpec
|
|
74
67
|
end
|
75
68
|
|
76
69
|
def predicate
|
77
|
-
|
70
|
+
# On 1.9, there appears to be a bug where String#match can return `false`
|
71
|
+
# rather than the match data object. Changing to Regex#match appears to
|
72
|
+
# work around this bug. For an example of this bug, see:
|
73
|
+
# https://travis-ci.org/rspec/rspec-expectations/jobs/27549635
|
74
|
+
@predicate ||= :"has_#{Matchers::HAS_REGEX.match(@method_name.to_s).captures.first}?"
|
78
75
|
end
|
79
76
|
|
80
77
|
def method_description
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
module BuiltIn
|
4
|
+
# @api private
|
5
|
+
# Provides the implementation for `have_attributes`.
|
6
|
+
# Not intended to be instantiated directly.
|
7
|
+
class HaveAttributes < BaseMatcher
|
8
|
+
# @private
|
9
|
+
attr_reader :respond_to_failed
|
10
|
+
|
11
|
+
def initialize(expected)
|
12
|
+
@expected = expected
|
13
|
+
@respond_to_failed = false
|
14
|
+
end
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
# @return [Boolean]
|
18
|
+
def matches?(actual)
|
19
|
+
@actual = actual
|
20
|
+
return false unless respond_to_attributes?
|
21
|
+
perform_match(:all?)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @api private
|
25
|
+
# @return [Boolean]
|
26
|
+
def does_not_match?(actual)
|
27
|
+
@actual = actual
|
28
|
+
return false unless respond_to_attributes?
|
29
|
+
perform_match(:none?)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
# @return [String]
|
34
|
+
def description
|
35
|
+
described_items = surface_descriptions_in(expected)
|
36
|
+
improve_hash_formatting "have attributes #{described_items.inspect}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# @api private
|
40
|
+
# @return [String]
|
41
|
+
def failure_message
|
42
|
+
respond_to_failure_message_or { super }
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api private
|
46
|
+
# @return [String]
|
47
|
+
def failure_message_when_negated
|
48
|
+
respond_to_failure_message_or { super }
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def perform_match(predicate)
|
54
|
+
expected.__send__(predicate) do |attribute_key, attribute_value|
|
55
|
+
actual_has_attribute?(attribute_key, attribute_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def actual_has_attribute?(attribute_key, attribute_value)
|
60
|
+
actual_value = actual.__send__(attribute_key)
|
61
|
+
values_match?(attribute_value, actual_value)
|
62
|
+
end
|
63
|
+
|
64
|
+
def respond_to_attributes?
|
65
|
+
matches = respond_to_matcher.matches?(actual)
|
66
|
+
@respond_to_failed = !matches
|
67
|
+
matches
|
68
|
+
end
|
69
|
+
|
70
|
+
def respond_to_matcher
|
71
|
+
@respond_to_matcher ||= RespondTo.new(*expected.keys).with(0).arguments
|
72
|
+
end
|
73
|
+
|
74
|
+
def respond_to_failure_message_or
|
75
|
+
if respond_to_failed
|
76
|
+
respond_to_matcher.failure_message
|
77
|
+
else
|
78
|
+
improve_hash_formatting(yield)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -4,6 +4,7 @@ module RSpec
|
|
4
4
|
# @api private
|
5
5
|
# Provides the implementation for `raise_error`.
|
6
6
|
# Not intended to be instantiated directly.
|
7
|
+
# rubocop:disable ClassLength
|
7
8
|
class RaiseError
|
8
9
|
include Composable
|
9
10
|
|
@@ -66,6 +67,10 @@ module RSpec
|
|
66
67
|
true
|
67
68
|
end
|
68
69
|
|
70
|
+
def expects_call_stack_jump?
|
71
|
+
true
|
72
|
+
end
|
73
|
+
|
69
74
|
# @api private
|
70
75
|
# @return [String]
|
71
76
|
def failure_message
|
@@ -163,6 +168,7 @@ module RSpec
|
|
163
168
|
raise "`expect { }.to raise_error(message).with_message(message)` is not valid. The matcher only allows the expected message to be specified once"
|
164
169
|
end
|
165
170
|
end
|
171
|
+
# rubocop:enable ClassLength
|
166
172
|
end
|
167
173
|
end
|
168
174
|
end
|
@@ -6,9 +6,7 @@ module RSpec
|
|
6
6
|
# @api private
|
7
7
|
# Provides the implementation for `respond_to`.
|
8
8
|
# Not intended to be instantiated directly.
|
9
|
-
class RespondTo
|
10
|
-
include Composable
|
11
|
-
|
9
|
+
class RespondTo < BaseMatcher
|
12
10
|
def initialize(*names)
|
13
11
|
@names = names
|
14
12
|
@expected_arity = nil
|
@@ -62,11 +60,6 @@ module RSpec
|
|
62
60
|
"respond to #{pp_names}#{with_arity}"
|
63
61
|
end
|
64
62
|
|
65
|
-
# @private
|
66
|
-
def supports_block_expectations?
|
67
|
-
false
|
68
|
-
end
|
69
|
-
|
70
63
|
private
|
71
64
|
|
72
65
|
def find_failing_method_names(actual, filter_method)
|
@@ -80,7 +73,7 @@ module RSpec
|
|
80
73
|
return true unless @expected_arity
|
81
74
|
|
82
75
|
signature = Support::MethodSignature.new(actual.method(name))
|
83
|
-
Support::
|
76
|
+
Support::StrictSignatureVerifier.new(signature, Array.new(@expected_arity)).valid?
|
84
77
|
end
|
85
78
|
|
86
79
|
def with_arity
|
@@ -4,9 +4,7 @@ module RSpec
|
|
4
4
|
# @api private
|
5
5
|
# Provides the implementation for `satisfy`.
|
6
6
|
# Not intended to be instantiated directly.
|
7
|
-
class Satisfy
|
8
|
-
include Composable
|
9
|
-
|
7
|
+
class Satisfy < BaseMatcher
|
10
8
|
def initialize(&block)
|
11
9
|
@block = block
|
12
10
|
end
|
@@ -35,11 +33,6 @@ module RSpec
|
|
35
33
|
def description
|
36
34
|
"satisfy block"
|
37
35
|
end
|
38
|
-
|
39
|
-
# @private
|
40
|
-
def supports_block_expectations?
|
41
|
-
false
|
42
|
-
end
|
43
36
|
end
|
44
37
|
end
|
45
38
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
RSpec::Support.require_rspec_support "method_signature_verifier"
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Matchers
|
3
5
|
module BuiltIn
|
@@ -68,10 +70,22 @@ module RSpec
|
|
68
70
|
"are."
|
69
71
|
end
|
70
72
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
if RUBY_VERSION.to_f > 1.8
|
74
|
+
def assert_valid_expect_block!
|
75
|
+
block_signature = RSpec::Support::BlockSignature.new(@block)
|
76
|
+
return if RSpec::Support::StrictSignatureVerifier.new(block_signature, [self]).valid?
|
77
|
+
raise "Your expect block must accept an argument to be used with this " \
|
78
|
+
"matcher. Pass the argument as a block on to the method you are testing."
|
79
|
+
end
|
80
|
+
else
|
81
|
+
# On 1.8.7, `lambda { }.arity` and `lambda { |*a| }.arity` both return -1,
|
82
|
+
# so we can't distinguish between accepting no args and an arg splat.
|
83
|
+
# It's OK to skip, this, though; it just provides a nice error message
|
84
|
+
# when the user forgets to accept an arg in their block. They'll still get
|
85
|
+
# the `assert_used!` error message from above, which is sufficient.
|
86
|
+
def assert_valid_expect_block!
|
87
|
+
# nothing to do
|
88
|
+
end
|
75
89
|
end
|
76
90
|
end
|
77
91
|
|
@@ -92,12 +106,19 @@ module RSpec
|
|
92
106
|
end
|
93
107
|
|
94
108
|
# @api public
|
95
|
-
# Specifies that the method is expected to yield
|
109
|
+
# Specifies that the method is expected to yield twice.
|
96
110
|
def twice
|
97
111
|
exactly(2)
|
98
112
|
self
|
99
113
|
end
|
100
114
|
|
115
|
+
# @api public
|
116
|
+
# Specifies that the method is expected to yield thrice.
|
117
|
+
def thrice
|
118
|
+
exactly(3)
|
119
|
+
self
|
120
|
+
end
|
121
|
+
|
101
122
|
# @api public
|
102
123
|
# Specifies that the method is expected to yield the given number of times.
|
103
124
|
def exactly(number)
|
@@ -167,6 +188,7 @@ module RSpec
|
|
167
188
|
when Numeric then n
|
168
189
|
when :once then 1
|
169
190
|
when :twice then 2
|
191
|
+
when :thrice then 3
|
170
192
|
end
|
171
193
|
end
|
172
194
|
|
@@ -241,9 +263,7 @@ module RSpec
|
|
241
263
|
# @api private
|
242
264
|
# Provides the implementation for `yield_with_args`.
|
243
265
|
# Not intended to be instantiated directly.
|
244
|
-
class YieldWithArgs
|
245
|
-
include Composable
|
246
|
-
|
266
|
+
class YieldWithArgs < BaseMatcher
|
247
267
|
def initialize(*args)
|
248
268
|
@expected = args
|
249
269
|
end
|
@@ -330,9 +350,7 @@ module RSpec
|
|
330
350
|
# @api private
|
331
351
|
# Provides the implementation for `yield_successive_args`.
|
332
352
|
# Not intended to be instantiated directly.
|
333
|
-
class YieldSuccessiveArgs
|
334
|
-
include Composable
|
335
|
-
|
353
|
+
class YieldSuccessiveArgs < BaseMatcher
|
336
354
|
def initialize(*args)
|
337
355
|
@expected = args
|
338
356
|
end
|
data/lib/rspec/matchers/dsl.rb
CHANGED
@@ -160,7 +160,10 @@ module RSpec
|
|
160
160
|
# Convenience for defining methods on this matcher to create a fluent
|
161
161
|
# interface. The trick about fluent interfaces is that each method must
|
162
162
|
# return self in order to chain methods together. `chain` handles that
|
163
|
-
# for you.
|
163
|
+
# for you. If the method is invoked and the
|
164
|
+
# `include_chain_clauses_in_custom_matcher_descriptions` config option
|
165
|
+
# hash been enabled, the chained method name and args will be added to the
|
166
|
+
# default description and failure message.
|
164
167
|
#
|
165
168
|
# @example
|
166
169
|
#
|
@@ -178,6 +181,7 @@ module RSpec
|
|
178
181
|
def chain(name, &definition)
|
179
182
|
define_user_override(name, definition) do |*args, &block|
|
180
183
|
super(*args, &block)
|
184
|
+
@chained_method_clauses.push([name, args])
|
181
185
|
self
|
182
186
|
end
|
183
187
|
end
|
@@ -249,17 +253,17 @@ module RSpec
|
|
249
253
|
|
250
254
|
# The default description.
|
251
255
|
def description
|
252
|
-
"#{name_to_sentence}#{to_sentence expected}"
|
256
|
+
"#{name_to_sentence}#{to_sentence expected}#{chained_method_clause_sentences}"
|
253
257
|
end
|
254
258
|
|
255
259
|
# The default failure message for positive expectations.
|
256
260
|
def failure_message
|
257
|
-
"expected #{actual.inspect} to #{
|
261
|
+
"expected #{actual.inspect} to #{description}"
|
258
262
|
end
|
259
263
|
|
260
264
|
# The default failure message for negative expectations.
|
261
265
|
def failure_message_when_negated
|
262
|
-
"expected #{actual.inspect} not to #{
|
266
|
+
"expected #{actual.inspect} not to #{description}"
|
263
267
|
end
|
264
268
|
|
265
269
|
# Matchers do not support block expectations by default. You
|
@@ -267,6 +271,21 @@ module RSpec
|
|
267
271
|
def supports_block_expectations?
|
268
272
|
false
|
269
273
|
end
|
274
|
+
|
275
|
+
# Most matchers do not expect call stack jumps.
|
276
|
+
def expects_call_stack_jump?
|
277
|
+
false
|
278
|
+
end
|
279
|
+
|
280
|
+
private
|
281
|
+
|
282
|
+
def chained_method_clause_sentences
|
283
|
+
return '' unless Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions?
|
284
|
+
|
285
|
+
@chained_method_clauses.map do |(method_name, method_args)|
|
286
|
+
" #{split_words(method_name)}#{to_sentence(method_args)}"
|
287
|
+
end.join
|
288
|
+
end
|
270
289
|
end
|
271
290
|
|
272
291
|
# The class used for custom matchers. The block passed to
|
@@ -304,6 +323,7 @@ module RSpec
|
|
304
323
|
@actual = nil
|
305
324
|
@expected_as_array = expected
|
306
325
|
@matcher_execution_context = matcher_execution_context
|
326
|
+
@chained_method_clauses = []
|
307
327
|
|
308
328
|
class << self
|
309
329
|
# See `Macros#define_user_override` above, for an explanation.
|
@@ -3,6 +3,7 @@ module RSpec
|
|
3
3
|
# Provides the necessary plumbing to wrap a matcher with a decorator.
|
4
4
|
# @private
|
5
5
|
class MatcherDelegator
|
6
|
+
include Composable
|
6
7
|
attr_reader :base_matcher
|
7
8
|
|
8
9
|
def initialize(base_matcher)
|
@@ -27,10 +28,6 @@ module RSpec
|
|
27
28
|
@base_matcher = @base_matcher.clone
|
28
29
|
super
|
29
30
|
end
|
30
|
-
|
31
|
-
# So `===` is delegated via `method_missing`.
|
32
|
-
undef ===
|
33
|
-
undef ==
|
34
31
|
end
|
35
32
|
end
|
36
33
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Matchers
|
3
|
+
# rspec-expectations can work with any matcher object that implements this protocol.
|
4
|
+
#
|
5
|
+
# @note This class is not loaded at runtime by rspec-expectations. It exists
|
6
|
+
# purely to provide documentation for the matcher protocol.
|
7
|
+
class MatcherProtocol
|
8
|
+
# @!group Required Methods
|
9
|
+
|
10
|
+
# @method matches?
|
11
|
+
# @param actual [Object] The object being matched against.
|
12
|
+
# @yield For an expression like `expect(x).to matcher do...end`, the `do/end`
|
13
|
+
# block binds to `to`. It passes that block, if there is one, on to this method.
|
14
|
+
# @return [Boolean] true if this matcher matches the provided object.
|
15
|
+
|
16
|
+
# @method failure_message
|
17
|
+
# This will only be called if {#matches?} returns false.
|
18
|
+
# @return [String] Explanation for the failure.
|
19
|
+
|
20
|
+
# @!endgroup
|
21
|
+
|
22
|
+
# @!group Optional Methods
|
23
|
+
|
24
|
+
# @method does_not_match?
|
25
|
+
# In a negative expectation such as `expect(x).not_to foo`, RSpec will
|
26
|
+
# call `foo.does_not_match?(x)` if this method is defined. If it's not
|
27
|
+
# defined it will fall back to using `!foo.matches?(x)`. This allows you
|
28
|
+
# to provide custom logic for the negative case.
|
29
|
+
#
|
30
|
+
# @param actual [Object] The object being matched against.
|
31
|
+
# @yield For an expression like `expect(x).not_to matcher do...end`, the `do/end`
|
32
|
+
# block binds to `not_to`. It passes that block, if there is one, on to this method.
|
33
|
+
# @return [Boolean] true if this matcher does not match the provided object.
|
34
|
+
|
35
|
+
# @method failure_message_when_negated
|
36
|
+
# This will only be called when a negative match fails.
|
37
|
+
# @return [String] Explanation for the failure.
|
38
|
+
# @note This method is listed as optional because matchers do not have to
|
39
|
+
# support negation. But if your matcher does support negation, this is a
|
40
|
+
# required method -- otherwise, you'll get a `NoMethodError`.
|
41
|
+
|
42
|
+
# @method description
|
43
|
+
# The description is used for two things:
|
44
|
+
#
|
45
|
+
# * When using RSpec's one-liner syntax
|
46
|
+
# (e.g. `it { is_expected.to matcher }`), the description
|
47
|
+
# is used to generate the example's doc string since you
|
48
|
+
# have not provided one.
|
49
|
+
# * In a composed matcher expression, the description is used
|
50
|
+
# as part of the failure message (and description) of the outer
|
51
|
+
# matcher.
|
52
|
+
#
|
53
|
+
# @return [String] Description of the matcher.
|
54
|
+
|
55
|
+
# @method supports_block_expectations?
|
56
|
+
# Indicates that this matcher can be used in a block expectation expression,
|
57
|
+
# such as `expect { foo }.to raise_error`. Generally speaking, this is
|
58
|
+
# only needed for matchers which operate on a side effect of a block, rather
|
59
|
+
# than on a particular object.
|
60
|
+
# @return [Boolean] true if this matcher can be used in block expressions.
|
61
|
+
# @note If not defined, RSpec assumes a value of `false` for this method.
|
62
|
+
|
63
|
+
# @method expects_call_stack_jump?
|
64
|
+
# Indicates that when this matcher is used in a block expectation
|
65
|
+
# expression, it expects the block to use a ruby construct that causes
|
66
|
+
# a call stack jump (such as raising an error or throwing a symbol).
|
67
|
+
#
|
68
|
+
# This is used internally for compound block expressions, as matchers
|
69
|
+
# which expect call stack jumps must be treated with care to work properly.
|
70
|
+
#
|
71
|
+
# @return [Boolean] true if the matcher expects a call stack jump
|
72
|
+
#
|
73
|
+
# @note This method is very rarely used or needed.
|
74
|
+
# @note If not defined, RSpec assumes a value of `false` for this method.
|
75
|
+
|
76
|
+
# @method diffable?
|
77
|
+
# @return [Boolean] true if `actual` and `expected` can be diffed.
|
78
|
+
# Indicates that this matcher provides `actual` and `expected` attributes,
|
79
|
+
# and that the values returned by these can be usefully diffed, which can
|
80
|
+
# be included in the output.
|
81
|
+
|
82
|
+
# @method actual
|
83
|
+
# @return [String, Object] If an object (rather than a string) is provided,
|
84
|
+
# RSpec will use the `pp` library to convert it to multi-line output in
|
85
|
+
# order to diff.
|
86
|
+
# The actual value for the purposes of a diff.
|
87
|
+
# @note This method is required if `diffable?` returns true.
|
88
|
+
|
89
|
+
# @method expected
|
90
|
+
# @return [String, Object] If an object (rather than a string) is provided,
|
91
|
+
# RSpec will use the `pp` library to convert it to multi-line output in
|
92
|
+
# order to diff.
|
93
|
+
# The expected value for the purposes of a diff.
|
94
|
+
# @note This method is required if `diffable?` returns true.
|
95
|
+
|
96
|
+
# @!endgroup
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-expectations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Baker
|
@@ -33,7 +33,7 @@ cert_chain:
|
|
33
33
|
1yHC1AcSYpvi2dAbOiHT5iQF+krm4wse8KctXgTNnjMsHEoGKulJS2/sZl90jcCz
|
34
34
|
muA=
|
35
35
|
-----END CERTIFICATE-----
|
36
|
-
date: 2014-
|
36
|
+
date: 2014-09-05 00:00:00.000000000 Z
|
37
37
|
dependencies:
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: rspec-support
|
@@ -41,14 +41,14 @@ dependencies:
|
|
41
41
|
requirements:
|
42
42
|
- - "~>"
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: 3.
|
44
|
+
version: 3.1.0
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
47
|
version_requirements: !ruby/object:Gem::Requirement
|
48
48
|
requirements:
|
49
49
|
- - "~>"
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version: 3.
|
51
|
+
version: 3.1.0
|
52
52
|
- !ruby/object:Gem::Dependency
|
53
53
|
name: diff-lcs
|
54
54
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +164,7 @@ files:
|
|
164
164
|
- lib/rspec/matchers/built_in/equal.rb
|
165
165
|
- lib/rspec/matchers/built_in/exist.rb
|
166
166
|
- lib/rspec/matchers/built_in/has.rb
|
167
|
+
- lib/rspec/matchers/built_in/have_attributes.rb
|
167
168
|
- lib/rspec/matchers/built_in/include.rb
|
168
169
|
- lib/rspec/matchers/built_in/match.rb
|
169
170
|
- lib/rspec/matchers/built_in/operators.rb
|
@@ -178,6 +179,7 @@ files:
|
|
178
179
|
- lib/rspec/matchers/dsl.rb
|
179
180
|
- lib/rspec/matchers/generated_descriptions.rb
|
180
181
|
- lib/rspec/matchers/matcher_delegator.rb
|
182
|
+
- lib/rspec/matchers/matcher_protocol.rb
|
181
183
|
- lib/rspec/matchers/pretty.rb
|
182
184
|
homepage: http://github.com/rspec/rspec-expectations
|
183
185
|
licenses:
|
@@ -203,6 +205,6 @@ rubyforge_project: rspec
|
|
203
205
|
rubygems_version: 2.2.2
|
204
206
|
signing_key:
|
205
207
|
specification_version: 4
|
206
|
-
summary: rspec-expectations-3.0
|
208
|
+
summary: rspec-expectations-3.1.0
|
207
209
|
test_files: []
|
208
210
|
has_rdoc:
|
metadata.gz.sig
CHANGED
Binary file
|