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 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