rspec-expectations 3.0.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|