rspec-expectations 3.8.5 → 3.9.3
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 +56 -1
- data/README.md +35 -20
- data/lib/rspec/expectations/expectation_target.rb +7 -43
- data/lib/rspec/expectations/handler.rb +2 -2
- data/lib/rspec/expectations/syntax.rb +1 -1
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +49 -30
- data/lib/rspec/matchers/built_in/base_matcher.rb +0 -5
- data/lib/rspec/matchers/built_in/be.rb +45 -9
- data/lib/rspec/matchers/built_in/be_within.rb +2 -2
- data/lib/rspec/matchers/built_in/change.rb +10 -15
- data/lib/rspec/matchers/built_in/compound.rb +6 -15
- data/lib/rspec/matchers/built_in/has.rb +24 -4
- data/lib/rspec/matchers/built_in/have_attributes.rb +1 -1
- data/lib/rspec/matchers/built_in/output.rb +2 -7
- data/lib/rspec/matchers/built_in/raise_error.rb +1 -6
- data/lib/rspec/matchers/built_in/respond_to.rb +37 -3
- data/lib/rspec/matchers/built_in/throw_symbol.rb +3 -6
- data/lib/rspec/matchers/built_in/yield.rb +49 -40
- data/lib/rspec/matchers/dsl.rb +16 -7
- data/lib/rspec/matchers/english_phrasing.rb +1 -1
- data/lib/rspec/matchers/expecteds_for_multiple_diffs.rb +16 -7
- data/lib/rspec/matchers/matcher_protocol.rb +0 -6
- metadata +24 -10
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba515bcbb264eef62d6948840e73b71ef3a68ed947d2e711df04fdf1b04fa4ec
|
4
|
+
data.tar.gz: ba8501df256831e843786ca4f78cc7825e8ad6dca125191beda504de0c1d16e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac2ff1267b689ba5daf08898a11ff97f1f2554db817f43135a6b1d96bcada94f03d728ddda4050158fcf8a483b8295644457aea810d18b37686d5aa253007917
|
7
|
+
data.tar.gz: 6527bed095e09131e0e8a50f12784d017953f073b4099d710df7fff638f632d03bedba40836adeba6aa33f51d9d4c501f795c364c6e1304ddc8c41225df2c18d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,58 @@
|
|
1
|
+
### 3.9.3 / 2020-10-23
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.2...v3.9.3)
|
3
|
+
|
4
|
+
Bug Fixes:
|
5
|
+
|
6
|
+
* Swap the comparison of the delta vs the expected for the `be_within` matcher allowing
|
7
|
+
more complicated oobjects to be compared providing they provide `abs` and other
|
8
|
+
comparison methods. (Kelly Stannard, #1182)
|
9
|
+
* Properly format expected in the description of the `be_within` matcher. (Jon Rowe, #1185)
|
10
|
+
* Remove warning when using keyword arguments with `be_` and `have_` matchers on 2.7.x
|
11
|
+
(Jon Rowe, #1187)
|
12
|
+
* Prevent formatting a single hash as a list of key value pairs in default failure messages
|
13
|
+
for custom matches (fixes formatting in `EnglishPhrasing#list`). (Robert Eshleman, #1193)
|
14
|
+
* Prevent errors from causing false positives when using `be <operator>` comparison, e.g.
|
15
|
+
`expect(1).not_to be < 'a'` will now correctly fail rather than pass. (Jon Rowe, #1208)
|
16
|
+
|
17
|
+
### 3.9.2 / 2020-05-08
|
18
|
+
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.1...v3.9.2)
|
19
|
+
|
20
|
+
Bug Fixes:
|
21
|
+
|
22
|
+
* Issue a proper `ArgumentError` when invalid arguments are given to `yield_control`
|
23
|
+
modifiers such as `at_least` et al. (Marc-André Lafortune, #1167)
|
24
|
+
* Prevent Ruby 2.7 keyword arguments warning from being issued by custom
|
25
|
+
matcher definitions. (Jon Rowe, #1176)
|
26
|
+
|
27
|
+
### 3.9.1 / 2020-03-13
|
28
|
+
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.9.0...v3.9.1)
|
29
|
+
|
30
|
+
Bug Fixes:
|
31
|
+
|
32
|
+
* Issue an improved warning when using `respond_to(...).with(n).arguments` and ignore
|
33
|
+
the warning when using with `have_attributes(...)`. (Jon Rowe, #1164)
|
34
|
+
|
35
|
+
### 3.9.0 / 2019-10-08
|
36
|
+
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.6...v3.9.0)
|
37
|
+
|
38
|
+
Enhancements:
|
39
|
+
|
40
|
+
* The `respond_to` matcher now uses the signature from `initialize` to validate checks
|
41
|
+
for `new` (unless `new` is non standard). (Jon Rowe, #1072)
|
42
|
+
* Generated descriptions for matchers now use `is expected to` rather than `should` in
|
43
|
+
line with our preferred DSL. (Pete Johns, #1080, rspec/rspec-core#2572)
|
44
|
+
* Add the ability to re-raise expectation errors when matching
|
45
|
+
with `match_when_negated` blocks. (Jon Rowe, #1130)
|
46
|
+
* Add a warning when an empty diff is produce due to identical inspect output.
|
47
|
+
(Benoit Tigeot, #1126)
|
48
|
+
|
49
|
+
### 3.8.6 / 2019-10-07
|
50
|
+
|
51
|
+
Bug Fixes:
|
52
|
+
|
53
|
+
* Revert #1125 due to the change being incompatible with our semantic versioning
|
54
|
+
policy.
|
55
|
+
|
1
56
|
### 3.8.5 / 2019-10-02
|
2
57
|
[Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.8.4...v3.8.5)
|
3
58
|
|
@@ -22,7 +77,7 @@ Bug Fixes:
|
|
22
77
|
* Prevent composed `all` matchers from leaking into their siblings leading to duplicate
|
23
78
|
failures. (Jamie English, #1086)
|
24
79
|
* Prevent objects which change their hash on comparison from failing change checks.
|
25
|
-
(Phil Pirozhkov, #
|
80
|
+
(Phil Pirozhkov, #1110)
|
26
81
|
* Issue an `ArgumentError` rather than a `NoMethodError` when `be_an_instance_of` and
|
27
82
|
`be_kind_of` matchers encounter objects not supporting those methods.
|
28
83
|
(Taichi Ishitani, #1107)
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# RSpec Expectations [](http://travis-ci.org/rspec/rspec-expectations) [](https://codeclimate.com/github/rspec/rspec-expectations)
|
2
2
|
|
3
3
|
RSpec::Expectations lets you express expected outcomes on an object in an
|
4
4
|
example.
|
@@ -15,12 +15,12 @@ rspec-core and rspec-mocks):
|
|
15
15
|
|
16
16
|
gem install rspec
|
17
17
|
|
18
|
-
Want to run against the `
|
18
|
+
Want to run against the `main` branch? You'll need to include the dependent
|
19
19
|
RSpec repos as well. Add the following to your `Gemfile`:
|
20
20
|
|
21
21
|
```ruby
|
22
22
|
%w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
|
23
|
-
gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => '
|
23
|
+
gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main'
|
24
24
|
end
|
25
25
|
```
|
26
26
|
|
@@ -175,30 +175,45 @@ expect(1..10).to cover(3)
|
|
175
175
|
### Collection membership
|
176
176
|
|
177
177
|
```ruby
|
178
|
-
|
178
|
+
# exact order, entire collection
|
179
|
+
expect(actual).to eq(expected)
|
180
|
+
|
181
|
+
# exact order, partial collection (based on an exact position)
|
179
182
|
expect(actual).to start_with(expected)
|
180
183
|
expect(actual).to end_with(expected)
|
181
184
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
+
# any order, entire collection
|
186
|
+
expect(actual).to match_array(expected)
|
187
|
+
|
188
|
+
# You can also express this by passing the expected elements
|
189
|
+
# as individual arguments
|
190
|
+
expect(actual).to contain_exactly(expected_element1, expected_element2)
|
191
|
+
|
192
|
+
# any order, partial collection
|
193
|
+
expect(actual).to include(expected)
|
185
194
|
```
|
186
195
|
|
187
196
|
#### Examples
|
188
197
|
|
189
198
|
```ruby
|
190
|
-
expect([1, 2, 3]).to
|
191
|
-
expect([1, 2, 3]).to include(1,
|
192
|
-
expect([1, 2, 3]).to
|
193
|
-
expect([1, 2, 3]).to start_with(1,
|
194
|
-
expect([1, 2, 3]).to
|
195
|
-
expect([1, 2, 3]).to end_with(
|
196
|
-
expect(
|
197
|
-
expect(
|
198
|
-
expect("this string").to
|
199
|
-
expect("this string").to
|
200
|
-
expect(
|
201
|
-
expect([1, 2, 3]).to
|
199
|
+
expect([1, 2, 3]).to eq([1, 2, 3]) # Order dependent equality check
|
200
|
+
expect([1, 2, 3]).to include(1) # Exact ordering, partial collection matches
|
201
|
+
expect([1, 2, 3]).to include(2, 3) #
|
202
|
+
expect([1, 2, 3]).to start_with(1) # As above, but from the start of the collection
|
203
|
+
expect([1, 2, 3]).to start_with(1, 2) #
|
204
|
+
expect([1, 2, 3]).to end_with(3) # As above but from the end of the collection
|
205
|
+
expect([1, 2, 3]).to end_with(2, 3) #
|
206
|
+
expect({:a => 'b'}).to include(:a => 'b') # Matching within hashes
|
207
|
+
expect("this string").to include("is str") # Matching within strings
|
208
|
+
expect("this string").to start_with("this") #
|
209
|
+
expect("this string").to end_with("ring") #
|
210
|
+
expect([1, 2, 3]).to contain_exactly(2, 3, 1) # Order independent matches
|
211
|
+
expect([1, 2, 3]).to match_array([3, 2, 1]) #
|
212
|
+
|
213
|
+
# Order dependent compound matchers
|
214
|
+
expect(
|
215
|
+
[{:a => 'hash'},{:a => 'another'}]
|
216
|
+
).to match([a_hash_including(:a => 'hash'), a_hash_including(:a => 'another')])
|
202
217
|
```
|
203
218
|
|
204
219
|
## `should` syntax
|
@@ -212,7 +227,7 @@ actual.should be > 3
|
|
212
227
|
[1, 2, 3].should_not include 4
|
213
228
|
```
|
214
229
|
|
215
|
-
See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/
|
230
|
+
See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/main/Should.md)
|
216
231
|
|
217
232
|
## Compound Matcher Expressions
|
218
233
|
|
@@ -33,16 +33,16 @@ module RSpec
|
|
33
33
|
end
|
34
34
|
|
35
35
|
# @private
|
36
|
-
def self.for(value,
|
36
|
+
def self.for(value, block)
|
37
37
|
if UndefinedValue.equal?(value)
|
38
|
-
unless
|
38
|
+
unless block
|
39
39
|
raise ArgumentError, "You must pass either an argument or a block to `expect`."
|
40
40
|
end
|
41
41
|
BlockExpectationTarget.new(block)
|
42
|
-
elsif
|
42
|
+
elsif block
|
43
43
|
raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
|
44
44
|
else
|
45
|
-
|
45
|
+
new(value)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -90,40 +90,6 @@ module RSpec
|
|
90
90
|
include InstanceMethods
|
91
91
|
end
|
92
92
|
|
93
|
-
# @private
|
94
|
-
# Validates the provided matcher to ensure it supports block
|
95
|
-
# expectations, in order to avoid user confusion when they
|
96
|
-
# use a block thinking the expectation will be on the return
|
97
|
-
# value of the block rather than the block itself.
|
98
|
-
class ValueExpectationTarget < ExpectationTarget
|
99
|
-
def to(matcher=nil, message=nil, &block)
|
100
|
-
enforce_value_expectation(matcher)
|
101
|
-
super
|
102
|
-
end
|
103
|
-
|
104
|
-
def not_to(matcher=nil, message=nil, &block)
|
105
|
-
enforce_value_expectation(matcher)
|
106
|
-
super
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
|
111
|
-
def enforce_value_expectation(matcher)
|
112
|
-
return if supports_value_expectations?(matcher)
|
113
|
-
|
114
|
-
raise ExpectationNotMetError, "You must pass a block rather than an argument to `expect` to use the provided " \
|
115
|
-
"block expectation matcher (#{RSpec::Support::ObjectFormatter.format(matcher)})."
|
116
|
-
end
|
117
|
-
|
118
|
-
def supports_value_expectations?(matcher)
|
119
|
-
if matcher.respond_to?(:supports_value_expectations?)
|
120
|
-
matcher.supports_value_expectations?
|
121
|
-
else
|
122
|
-
true
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
93
|
# @private
|
128
94
|
# Validates the provided matcher to ensure it supports block
|
129
95
|
# expectations, in order to avoid user confusion when they
|
@@ -152,11 +118,9 @@ module RSpec
|
|
152
118
|
end
|
153
119
|
|
154
120
|
def supports_block_expectations?(matcher)
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
false
|
159
|
-
end
|
121
|
+
matcher.supports_block_expectations?
|
122
|
+
rescue NoMethodError
|
123
|
+
false
|
160
124
|
end
|
161
125
|
end
|
162
126
|
end
|
@@ -52,7 +52,7 @@ module RSpec
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def self.verb
|
55
|
-
|
55
|
+
'is expected to'
|
56
56
|
end
|
57
57
|
|
58
58
|
def self.should_method
|
@@ -82,7 +82,7 @@ module RSpec
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.verb
|
85
|
-
|
85
|
+
'is expected not to'
|
86
86
|
end
|
87
87
|
|
88
88
|
def self.should_method
|
@@ -70,7 +70,7 @@ module RSpec
|
|
70
70
|
|
71
71
|
syntax_host.module_exec do
|
72
72
|
def expect(value=::RSpec::Expectations::ExpectationTarget::UndefinedValue, &block)
|
73
|
-
::RSpec::Expectations::ExpectationTarget.for(value,
|
73
|
+
::RSpec::Expectations::ExpectationTarget.for(value, block)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
data/lib/rspec/matchers.rb
CHANGED
@@ -238,7 +238,7 @@ module RSpec
|
|
238
238
|
# best to find a more positive name for the negated form, such as
|
239
239
|
# `avoid_changing` rather than `not_change`.
|
240
240
|
#
|
241
|
-
module Matchers
|
241
|
+
module Matchers # rubocop:disable Metrics/ModuleLength
|
242
242
|
extend ::RSpec::Matchers::DSL
|
243
243
|
|
244
244
|
# @!macro [attach] alias_matcher
|
@@ -953,14 +953,29 @@ module RSpec
|
|
953
953
|
HAS_REGEX = /^(?:have_)(.*)/
|
954
954
|
DYNAMIC_MATCHER_REGEX = Regexp.union(BE_PREDICATE_REGEX, HAS_REGEX)
|
955
955
|
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
956
|
+
if RSpec::Support::RubyFeatures.kw_args_supported?
|
957
|
+
binding.eval(<<-CODE, __FILE__, __LINE__)
|
958
|
+
def method_missing(method, *args, **kwargs, &block)
|
959
|
+
case method.to_s
|
960
|
+
when BE_PREDICATE_REGEX
|
961
|
+
BuiltIn::BePredicate.new(method, *args, **kwargs, &block)
|
962
|
+
when HAS_REGEX
|
963
|
+
BuiltIn::Has.new(method, *args, **kwargs, &block)
|
964
|
+
else
|
965
|
+
super
|
966
|
+
end
|
967
|
+
end
|
968
|
+
CODE
|
969
|
+
else
|
970
|
+
def method_missing(method, *args, &block)
|
971
|
+
case method.to_s
|
972
|
+
when BE_PREDICATE_REGEX
|
973
|
+
BuiltIn::BePredicate.new(method, *args, &block)
|
974
|
+
when HAS_REGEX
|
975
|
+
BuiltIn::Has.new(method, *args, &block)
|
976
|
+
else
|
977
|
+
super
|
978
|
+
end
|
964
979
|
end
|
965
980
|
end
|
966
981
|
|
@@ -1003,31 +1018,35 @@ module RSpec
|
|
1003
1018
|
is_a_matcher?(obj) && obj.respond_to?(:description)
|
1004
1019
|
end
|
1005
1020
|
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1021
|
+
class << self
|
1022
|
+
private
|
1023
|
+
|
1024
|
+
if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9'
|
1025
|
+
# Note that `included` doesn't work for this because it is triggered
|
1026
|
+
# _after_ `RSpec::Matchers` is an ancestor of the inclusion host, rather
|
1027
|
+
# than _before_, like `append_features`. It's important we check this before
|
1028
|
+
# in order to find the cases where it was already previously included.
|
1029
|
+
# @api private
|
1030
|
+
def append_features(mod)
|
1031
|
+
return super if mod < self # `mod < self` indicates a re-inclusion.
|
1014
1032
|
|
1015
|
-
|
1016
|
-
|
1033
|
+
subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self }
|
1034
|
+
return super unless subclasses.any?
|
1017
1035
|
|
1018
|
-
|
1019
|
-
|
1036
|
+
subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor.
|
1037
|
+
subclasses = subclasses.map { |s| "`#{s}`" }.join(", ")
|
1020
1038
|
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1039
|
+
RSpec.warning "`#{self}` has been included in a superclass (`#{mod}`) " \
|
1040
|
+
"after previously being included in subclasses (#{subclasses}), " \
|
1041
|
+
"which can trigger infinite recursion from `super` due to an MRI 1.9 bug " \
|
1042
|
+
"(https://redmine.ruby-lang.org/issues/3351). To work around this, " \
|
1043
|
+
"either upgrade to MRI 2.0+, include a dup of the module (e.g. " \
|
1044
|
+
"`include #{self}.dup`), or find a way to include `#{self}` in `#{mod}` " \
|
1045
|
+
"before it is included in subclasses (#{subclasses}). See " \
|
1046
|
+
"https://github.com/rspec/rspec-expectations/issues/814 for more info"
|
1029
1047
|
|
1030
|
-
|
1048
|
+
super
|
1049
|
+
end
|
1031
1050
|
end
|
1032
1051
|
end
|
1033
1052
|
end
|
@@ -143,8 +143,13 @@ module RSpec
|
|
143
143
|
end
|
144
144
|
|
145
145
|
def matches?(actual)
|
146
|
-
|
147
|
-
|
146
|
+
perform_match(actual)
|
147
|
+
rescue ArgumentError, NoMethodError
|
148
|
+
false
|
149
|
+
end
|
150
|
+
|
151
|
+
def does_not_match?(actual)
|
152
|
+
!perform_match(actual)
|
148
153
|
rescue ArgumentError, NoMethodError
|
149
154
|
false
|
150
155
|
end
|
@@ -173,6 +178,13 @@ module RSpec
|
|
173
178
|
def description
|
174
179
|
"be #{@operator} #{expected_to_sentence}#{args_to_sentence}"
|
175
180
|
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def perform_match(actual)
|
185
|
+
@actual = actual
|
186
|
+
@actual.__send__ @operator, @expected
|
187
|
+
end
|
176
188
|
end
|
177
189
|
|
178
190
|
# @api private
|
@@ -181,10 +193,21 @@ module RSpec
|
|
181
193
|
class BePredicate < BaseMatcher
|
182
194
|
include BeHelpers
|
183
195
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
196
|
+
if RSpec::Support::RubyFeatures.kw_args_supported?
|
197
|
+
binding.eval(<<-CODE, __FILE__, __LINE__)
|
198
|
+
def initialize(*args, **kwargs, &block)
|
199
|
+
@expected = parse_expected(args.shift)
|
200
|
+
@args = args
|
201
|
+
@kwargs = kwargs
|
202
|
+
@block = block
|
203
|
+
end
|
204
|
+
CODE
|
205
|
+
else
|
206
|
+
def initialize(*args, &block)
|
207
|
+
@expected = parse_expected(args.shift)
|
208
|
+
@args = args
|
209
|
+
@block = block
|
210
|
+
end
|
188
211
|
end
|
189
212
|
|
190
213
|
def matches?(actual, &block)
|
@@ -236,9 +259,22 @@ module RSpec
|
|
236
259
|
end
|
237
260
|
end
|
238
261
|
|
239
|
-
|
240
|
-
|
241
|
-
|
262
|
+
if RSpec::Support::RubyFeatures.kw_args_supported?
|
263
|
+
binding.eval(<<-CODE, __FILE__, __LINE__)
|
264
|
+
def predicate_matches?
|
265
|
+
method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate
|
266
|
+
if @kwargs.empty?
|
267
|
+
@predicate_matches = actual.__send__(method_name, *@args, &@block)
|
268
|
+
else
|
269
|
+
@predicate_matches = actual.__send__(method_name, *@args, **@kwargs, &@block)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
CODE
|
273
|
+
else
|
274
|
+
def predicate_matches?
|
275
|
+
method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate
|
276
|
+
@predicate_matches = actual.__send__(method_name, *@args, &@block)
|
277
|
+
end
|
242
278
|
end
|
243
279
|
|
244
280
|
def predicate
|