rspec-expectations 3.8.5 → 3.9.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58597a62f47f10ecd74eda0086bcee4ca68878120d63cc670ebae37f9db1d252
4
- data.tar.gz: 7443ec753991ae3c88ac9be2e8a22aab784b7e10bd2be481bf8a83daf3b85778
3
+ metadata.gz: ba515bcbb264eef62d6948840e73b71ef3a68ed947d2e711df04fdf1b04fa4ec
4
+ data.tar.gz: ba8501df256831e843786ca4f78cc7825e8ad6dca125191beda504de0c1d16e7
5
5
  SHA512:
6
- metadata.gz: 36dab83e0399bbf5c58f17f3302c865ca4ec92123c97cc6eea1f9bf80a5466e643adfbd3056e46a653c5bbc08fc93f5d804bc9ca4a2e841468b22f09e2a140ec
7
- data.tar.gz: f4b9263c27571536fa276eefee5a2c115a9f1f3d070f1abcaf4fba9e5e2cd2f11e04f48d146c870b26d019f6fb8533b3e2b605ff422ab32832f51d1531743515
6
+ metadata.gz: ac2ff1267b689ba5daf08898a11ff97f1f2554db817f43135a6b1d96bcada94f03d728ddda4050158fcf8a483b8295644457aea810d18b37686d5aa253007917
7
+ data.tar.gz: 6527bed095e09131e0e8a50f12784d017953f073b4099d710df7fff638f632d03bedba40836adeba6aa33f51d9d4c501f795c364c6e1304ddc8c41225df2c18d
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -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, #1100)
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 [![Build Status](https://secure.travis-ci.org/rspec/rspec-expectations.svg?branch=master)](http://travis-ci.org/rspec/rspec-expectations) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](https://codeclimate.com/github/rspec/rspec-expectations)
1
+ # RSpec Expectations [![Build Status](https://secure.travis-ci.org/rspec/rspec-expectations.svg?branch=main)](http://travis-ci.org/rspec/rspec-expectations) [![Code Climate](https://codeclimate.com/github/rspec/rspec-expectations.svg)](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 `master` branch? You'll need to include the dependent
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 => 'master'
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
- expect(actual).to include(expected)
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
- expect(actual).to contain_exactly(individual, items)
183
- # ...which is the same as:
184
- expect(actual).to match_array(expected_array)
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 include(1)
191
- expect([1, 2, 3]).to include(1, 2)
192
- expect([1, 2, 3]).to start_with(1)
193
- expect([1, 2, 3]).to start_with(1, 2)
194
- expect([1, 2, 3]).to end_with(3)
195
- expect([1, 2, 3]).to end_with(2, 3)
196
- expect({:a => 'b'}).to include(:a => 'b')
197
- expect("this string").to include("is str")
198
- expect("this string").to start_with("this")
199
- expect("this string").to end_with("ring")
200
- expect([1, 2, 3]).to contain_exactly(2, 3, 1)
201
- expect([1, 2, 3]).to match_array([3, 2, 1])
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/master/Should.md)
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, &block)
36
+ def self.for(value, block)
37
37
  if UndefinedValue.equal?(value)
38
- unless block_given?
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 block_given?
42
+ elsif block
43
43
  raise ArgumentError, "You cannot pass both an argument and a block to `expect`."
44
44
  else
45
- ValueExpectationTarget.new(value)
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
- if matcher.respond_to?(:supports_block_expectations?)
156
- matcher.supports_block_expectations?
157
- else
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
- "should"
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
- "should not"
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, &block)
73
+ ::RSpec::Expectations::ExpectationTarget.for(value, block)
74
74
  end
75
75
  end
76
76
  end
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Expectations
3
3
  # @private
4
4
  module Version
5
- STRING = '3.8.5'
5
+ STRING = '3.9.3'
6
6
  end
7
7
  end
8
8
  end
@@ -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
- def method_missing(method, *args, &block)
957
- case method.to_s
958
- when BE_PREDICATE_REGEX
959
- BuiltIn::BePredicate.new(method, *args, &block)
960
- when HAS_REGEX
961
- BuiltIn::Has.new(method, *args, &block)
962
- else
963
- super
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
- if RSpec::Support::Ruby.mri? && RUBY_VERSION[0, 3] == '1.9'
1007
- # @api private
1008
- # Note that `included` doesn't work for this because it is triggered
1009
- # _after_ `RSpec::Matchers` is an ancestor of the inclusion host, rather
1010
- # than _before_, like `append_features`. It's important we check this before
1011
- # in order to find the cases where it was already previously included.
1012
- def self.append_features(mod)
1013
- return super if mod < self # `mod < self` indicates a re-inclusion.
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
- subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self }
1016
- return super unless subclasses.any?
1033
+ subclasses = ObjectSpace.each_object(Class).select { |c| c < mod && c < self }
1034
+ return super unless subclasses.any?
1017
1035
 
1018
- subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor.
1019
- subclasses = subclasses.map { |s| "`#{s}`" }.join(", ")
1036
+ subclasses.reject! { |s| subclasses.any? { |s2| s < s2 } } # Filter to the root ancestor.
1037
+ subclasses = subclasses.map { |s| "`#{s}`" }.join(", ")
1020
1038
 
1021
- RSpec.warning "`#{self}` has been included in a superclass (`#{mod}`) " \
1022
- "after previously being included in subclasses (#{subclasses}), " \
1023
- "which can trigger infinite recursion from `super` due to an MRI 1.9 bug " \
1024
- "(https://redmine.ruby-lang.org/issues/3351). To work around this, " \
1025
- "either upgrade to MRI 2.0+, include a dup of the module (e.g. " \
1026
- "`include #{self}.dup`), or find a way to include `#{self}` in `#{mod}` " \
1027
- "before it is included in subclasses (#{subclasses}). See " \
1028
- "https://github.com/rspec/rspec-expectations/issues/814 for more info"
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
- super
1048
+ super
1049
+ end
1031
1050
  end
1032
1051
  end
1033
1052
  end
@@ -78,11 +78,6 @@ module RSpec
78
78
  false
79
79
  end
80
80
 
81
- # @private
82
- def supports_value_expectations?
83
- true
84
- end
85
-
86
81
  # @api private
87
82
  def expects_call_stack_jump?
88
83
  false
@@ -143,8 +143,13 @@ module RSpec
143
143
  end
144
144
 
145
145
  def matches?(actual)
146
- @actual = actual
147
- @actual.__send__ @operator, @expected
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
- def initialize(*args, &block)
185
- @expected = parse_expected(args.shift)
186
- @args = args
187
- @block = block
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
- def predicate_matches?
240
- method_name = actual.respond_to?(predicate) ? predicate : present_tense_predicate
241
- @predicate_matches = actual.__send__(method_name, *@args, &@block)
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