rspec-expectations 3.11.0 → 3.13.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +90 -5
  4. data/README.md +10 -4
  5. data/lib/rspec/expectations/block_snippet_extractor.rb +2 -0
  6. data/lib/rspec/expectations/configuration.rb +5 -0
  7. data/lib/rspec/expectations/fail_with.rb +1 -1
  8. data/lib/rspec/expectations/failure_aggregator.rb +24 -0
  9. data/lib/rspec/expectations/handler.rb +4 -5
  10. data/lib/rspec/expectations/version.rb +1 -1
  11. data/lib/rspec/matchers/aliased_matcher.rb +3 -3
  12. data/lib/rspec/matchers/built_in/base_matcher.rb +45 -18
  13. data/lib/rspec/matchers/built_in/change.rb +2 -0
  14. data/lib/rspec/matchers/built_in/compound.rb +7 -4
  15. data/lib/rspec/matchers/built_in/contain_exactly.rb +12 -2
  16. data/lib/rspec/matchers/built_in/count_expectation.rb +3 -1
  17. data/lib/rspec/matchers/built_in/eq.rb +5 -1
  18. data/lib/rspec/matchers/built_in/eql.rb +5 -1
  19. data/lib/rspec/matchers/built_in/exist.rb +1 -1
  20. data/lib/rspec/matchers/built_in/has.rb +29 -2
  21. data/lib/rspec/matchers/built_in/include.rb +14 -2
  22. data/lib/rspec/matchers/built_in/match.rb +2 -0
  23. data/lib/rspec/matchers/built_in/raise_error.rb +11 -7
  24. data/lib/rspec/matchers/built_in/satisfy.rb +2 -0
  25. data/lib/rspec/matchers/built_in/throw_symbol.rb +4 -4
  26. data/lib/rspec/matchers/composable.rb +1 -1
  27. data/lib/rspec/matchers/dsl.rb +10 -9
  28. data/lib/rspec/matchers/english_phrasing.rb +2 -0
  29. data/lib/rspec/matchers/matcher_delegator.rb +27 -1
  30. data/lib/rspec/matchers/{expecteds_for_multiple_diffs.rb → multi_matcher_diff.rb} +16 -16
  31. data/lib/rspec/matchers.rb +10 -5
  32. data.tar.gz.sig +0 -0
  33. metadata +8 -8
  34. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e651e80dd869915779a72a9ea43b38d20327f3dbfaf94a4851eff7974d1f3d0a
4
- data.tar.gz: e1788055c911b97cbad1b3747fe9b9be005a999e2e97e6c361df4c91fa4fda25
3
+ metadata.gz: 2326091f61f5fccf3b86b2275c850340614475381f32a9f22417cb9f59b80ab3
4
+ data.tar.gz: 7602b8b98d0dc9fecc754156a01686a131fedd6d43fe1b8ce8f689f0fba3b469
5
5
  SHA512:
6
- metadata.gz: ec1b6b68b80fddae764dbf88312817c35c1e76228c29748e2b89d8d9a69d95384aa4fe9daf7b8a650dd307dd32aca13bae590d8960f0989beea67c54f7f6d7d5
7
- data.tar.gz: 7a8a129e74ccec6299ab3af1c728cab2754a1cc98911507704c3f52a01c33b321250bfe715deef835b61963e22c66ec878500d10c6fea93d4fda7cc39b101676
6
+ metadata.gz: 21d9a95f4e9cb3fa1b7fb99419861bc90a39ee33b4fa183a1018ab351d830168bd93fb02e00452344e1c8d9824bc3d0543b988e42288396c8a3091b9fc5d6f9c
7
+ data.tar.gz: ec4864365250340370d370af68dee725f3d018e414e57506d21d173e9d0a69a9df258f7d7a11e8f2ff583f4060348a76bb3251aa09a29add0ddee6fb2b0d4192
checksums.yaml.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,5 +1,92 @@
1
1
  ### Development
2
- [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.0...3-11-maintenance)
2
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.13.3...3-13-maintenance)
3
+
4
+ ### 3.13.3 / 2024-09-07
5
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.13.2...v3.13.3)
6
+
7
+ Bug Fixes:
8
+
9
+ * Fix passing a regular expression to the `include` matcher without a count constraint.
10
+ (Jon Rowe, #1485)
11
+
12
+ ### 3.13.2 / 2024-08-20
13
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.13.1...v3.13.2)
14
+
15
+ Bug Fixes:
16
+
17
+ * When using null object doubles, prevent typos triggering dynamic matchers.
18
+ (Eric Mueller, #1455)
19
+ * Use `RSpec.warning` for an expectation warning rather than `Kernel.warn`. (Jon Rowe, #1472)
20
+ * Prevent mismatched use of block and value matchers in compound expectations. (Phil Pirozhkov, #1476)
21
+ * Raise an error when passing no arguments to the `include` matcher. (Eric Mueller, #1479)
22
+
23
+ ### 3.13.1 / 2024-06-13
24
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.13.0...v3.13.1)
25
+
26
+ Bug Fixes:
27
+
28
+ * Fix the "false positive" warning message when using a negated `raise_error` matcher
29
+ with a `RegExp` instance. (Eric Mueller, #1456)
30
+
31
+ ### 3.13.0 / 2024-02-04
32
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.4...v3.13.0)
33
+
34
+ Enhancements:
35
+
36
+ * Update `eq` and `eql` matchers to better highlight difference in string encoding.
37
+ (Alan Foster, #1425)
38
+
39
+ ### 3.12.4 / 2024-02-04
40
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.3...v3.12.4)
41
+
42
+ Bug Fixes:
43
+
44
+ * Fix the diff for redefined `actual` and reassigned `@actual` in compound
45
+ expectations failure messages. (Phil Pirozhkov, #1440)
46
+
47
+ ### 3.12.3 / 2023-04-20
48
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.2...v3.12.3)
49
+
50
+ Bug Fixes:
51
+
52
+ * Fix `include` matcher when fuzzy matching on keys with a hash-like actual which
53
+ has a non standard `key?` method which may raise.
54
+ (Jon Rowe, #1416)
55
+
56
+ ### 3.12.2 / 2023-01-07
57
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.1...v3.12.2)
58
+
59
+ Bug Fixes:
60
+
61
+ * Prevent deprecation warning when using the `exist` matcher with `Dir`.
62
+ (Steve Dierker, #1398)
63
+
64
+ ### 3.12.1 / 2022-12-16
65
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.12.0...v3.12.1)
66
+
67
+ Bug Fixes:
68
+
69
+ * Pass keyword arguments through to aliased (and thus negated) matchers. (Jon Rowe, #1394)
70
+ * When handling failures in an aggregated_failures block (or example) prevent
71
+ the failure list leaking out. (Maciek Rząsa, #1392)
72
+
73
+ ### 3.12.0 / 2022-10-26
74
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.1...v3.12.0)
75
+
76
+ Enhancements:
77
+
78
+ * Add `an_array_matching` alias for `match_array` to improve readability as an argument
79
+ matcher. (Mark Schneider, #1361)
80
+
81
+ ### 3.11.1 / 2022-09-12
82
+ [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.11.0...v3.11.1)
83
+
84
+ Bug Fixes:
85
+
86
+ * Allow the `contain_exactly` matcher to be reused by resetting its
87
+ internals on `matches?` (@bclayman-sq, #1326)
88
+ * Using the exist matcher on `FileTest` no longer produces a deprecation warning.
89
+ (Ryo Nakamura, #1383)
3
90
 
4
91
  ### 3.11.0 / 2022-02-09
5
92
  [Full Changelog](http://github.com/rspec/rspec-expectations/compare/v3.10.2...v3.11.0)
@@ -296,10 +383,8 @@ Enhancements:
296
383
  can cause uses of `super` to trigger infinite recursion. (Myron Marston, #816)
297
384
  * Stop rescuing `NoMemoryError`, `SignalExcepetion`, `Interrupt` and
298
385
  `SystemExit`. It is dangerous to interfere with these. (Myron Marston, #845)
299
- * Add `#with_captures` to the
300
- [match matcher](https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/match-matcher)
301
- which allows a user to specify expected captures when matching a regex
302
- against a string. (Sam Phippen, #848)
386
+ * Add `#with_captures` to the match matcher which allows a user to specify expected
387
+ captures when matching a regex against a string. (Sam Phippen, #848)
303
388
  * Always print compound failure messages in the multi-line form. Trying
304
389
  to print it all on a single line didn't read very well. (Myron Marston, #859)
305
390
 
data/README.md CHANGED
@@ -13,7 +13,9 @@ If you want to use rspec-expectations with rspec, just install the rspec gem
13
13
  and RubyGems will also install rspec-expectations for you (along with
14
14
  rspec-core and rspec-mocks):
15
15
 
16
- gem install rspec
16
+ ```shell
17
+ gem install rspec
18
+ ```
17
19
 
18
20
  Want to run against the `main` branch? You'll need to include the dependent
19
21
  RSpec repos as well. Add the following to your `Gemfile`:
@@ -27,7 +29,9 @@ end
27
29
  If you want to use rspec-expectations with another tool, like Test::Unit,
28
30
  Minitest, or Cucumber, you can install it directly:
29
31
 
30
- gem install rspec-expectations
32
+ ```shell
33
+ gem install rspec-expectations
34
+ ```
31
35
 
32
36
  ## Contributing
33
37
 
@@ -67,8 +71,10 @@ The `describe` and `it` methods come from rspec-core. The `Order`, `LineItem`,
67
71
  expresses an expected outcome. If `order.total == Money.new(5.55, :USD)`, then
68
72
  the example passes. If not, it fails with a message like:
69
73
 
70
- expected: #<Money @value=5.55 @currency=:USD>
71
- got: #<Money @value=1.11 @currency=:USD>
74
+ ```
75
+ expected: #<Money @value=5.55 @currency=:USD>
76
+ got: #<Money @value=1.11 @currency=:USD>
77
+ ```
72
78
 
73
79
  ## Built-in matchers
74
80
 
@@ -46,11 +46,13 @@ module RSpec
46
46
  RSpec.world.source_from_file(file_path)
47
47
  end
48
48
  else
49
+ # :nocov:
49
50
  RSpec::Support.require_rspec_support 'source'
50
51
  def source
51
52
  raise TargetNotFoundError unless File.exist?(file_path)
52
53
  @source ||= RSpec::Support::Source.from_file(file_path)
53
54
  end
55
+ # :nocov:
54
56
  end
55
57
 
56
58
  def file_path
@@ -89,6 +89,7 @@ module RSpec
89
89
  ::RSpec.configuration.color_enabled?
90
90
  end
91
91
  else
92
+ # :nocov:
92
93
  # Indicates whether or not diffs should be colored.
93
94
  # Delegates to rspec-core's color option if rspec-core
94
95
  # is loaded; otherwise you can set it here.
@@ -100,8 +101,11 @@ module RSpec
100
101
  def color?
101
102
  defined?(@color) && @color
102
103
  end
104
+ # :nocov:
103
105
  end
104
106
 
107
+ # :nocov: Because this is only really _useful_ on 1.8, and hard to test elsewhere.
108
+ #
105
109
  # Adds `should` and `should_not` to the given classes
106
110
  # or modules. This can be used to ensure `should` works
107
111
  # properly on things like proxy objects (particular
@@ -114,6 +118,7 @@ module RSpec
114
118
  Expectations::Syntax.enable_should(mod)
115
119
  end
116
120
  end
121
+ # :nocov:
117
122
 
118
123
  # Sets or gets the backtrace formatter. The backtrace formatter should
119
124
  # implement `#format_backtrace(Array<String>)`. This is used
@@ -30,7 +30,7 @@ module RSpec
30
30
  "appropriate failure_message[_when_negated] method to return a string?"
31
31
  end
32
32
 
33
- message = ::RSpec::Matchers::ExpectedsForMultipleDiffs.from(expected).message_with_diff(message, differ, actual)
33
+ message = ::RSpec::Matchers::MultiMatcherDiff.from(expected, actual).message_with_diff(message, differ)
34
34
 
35
35
  RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message)
36
36
  end
@@ -4,6 +4,26 @@ module RSpec
4
4
  class FailureAggregator
5
5
  attr_reader :block_label, :metadata
6
6
 
7
+ # @private
8
+ class AggregatedFailure
9
+ # :nocov:
10
+ # `inspect` was apparently used by some versions early in ruby 3 while constructing
11
+ # NoMethodError, but seems to be no longer.
12
+ #
13
+ # @private
14
+ MESSAGE =
15
+ 'AggregatedFailure: This method caused a failure which has been ' \
16
+ 'suppressed to be aggregated into our failure report by returning ' \
17
+ 'this value, further errors can be ignored.'
18
+
19
+ def inspect
20
+ MESSAGE
21
+ end
22
+ # :nocov:
23
+ end
24
+
25
+ AGGREGATED_FAILURE = AggregatedFailure.new
26
+
7
27
  def aggregate
8
28
  RSpec::Support.with_failure_notifier(self) do
9
29
  begin
@@ -48,6 +68,8 @@ module RSpec
48
68
  @seen_source_ids[source_id] = true
49
69
  assign_backtrace(failure) unless failure.backtrace
50
70
  failures << failure
71
+
72
+ AGGREGATED_FAILURE
51
73
  end
52
74
 
53
75
  private
@@ -58,11 +80,13 @@ module RSpec
58
80
  # a backtrace that has a continuous common section with the raised `MultipleExpectationsNotMetError`,
59
81
  # so that rspec-core's truncation logic can work properly on it to list the backtrace
60
82
  # relative to the `aggregate_failures` block.
83
+ # :nocov:
61
84
  def assign_backtrace(failure)
62
85
  raise failure
63
86
  rescue failure.class => e
64
87
  failure.set_backtrace(e.backtrace)
65
88
  end
89
+ # :nocov:
66
90
  else
67
91
  # Using `caller` performs better (and is simpler) than `raise` on most Rubies.
68
92
  def assign_backtrace(failure)
@@ -4,11 +4,10 @@ module RSpec
4
4
  module ExpectationHelper
5
5
  def self.check_message(msg)
6
6
  unless msg.nil? || msg.respond_to?(:to_str) || msg.respond_to?(:call)
7
- ::Kernel.warn [
8
- "WARNING: ignoring the provided expectation message argument (",
9
- msg.inspect,
10
- ") since it is not a string or a proc."
11
- ].join
7
+ RSpec.warning(
8
+ "ignoring the provided expectation message argument" \
9
+ "(#{ msg.inspect }) since it is not a string or a proc"
10
+ )
12
11
  end
13
12
  end
14
13
 
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Expectations
3
3
  # @private
4
4
  module Version
5
- STRING = '3.11.0'
5
+ STRING = '3.13.3'
6
6
  end
7
7
  end
8
8
  end
@@ -99,14 +99,14 @@ module RSpec
99
99
  # by going through the effort of defining a negated matcher.
100
100
  #
101
101
  # However, if the override didn't actually change anything, then we
102
- # should return the opposite failure message instead -- the overriden
102
+ # should return the opposite failure message instead -- the overridden
103
103
  # message is going to be confusing if we return it as-is, as it represents
104
104
  # the non-negated failure message for a negated match (or vice versa).
105
105
  def optimal_failure_message(same, inverted)
106
106
  if DefaultFailureMessages.has_default_failure_messages?(@base_matcher)
107
107
  base_message = @base_matcher.__send__(same)
108
- overriden = @description_block.call(base_message)
109
- return overriden if overriden != base_message
108
+ overridden = @description_block.call(base_message)
109
+ return overridden if overridden != base_message
110
110
  end
111
111
 
112
112
  @base_matcher.__send__(inverted)
@@ -124,24 +124,6 @@ module RSpec
124
124
  end
125
125
  private_class_method :underscore
126
126
 
127
- private
128
-
129
- def assert_ivars(*expected_ivars)
130
- return unless (expected_ivars - present_ivars).any?
131
- ivar_list = EnglishPhrasing.list(expected_ivars)
132
- raise "#{self.class.name} needs to supply#{ivar_list}"
133
- end
134
-
135
- if RUBY_VERSION.to_f < 1.9
136
- # :nocov:
137
- def present_ivars
138
- instance_variables.map(&:to_sym)
139
- end
140
- # :nocov:
141
- else
142
- alias present_ivars instance_variables
143
- end
144
-
145
127
  # @private
146
128
  module HashFormatting
147
129
  # `{ :a => 5, :b => 2 }.inspect` produces:
@@ -161,6 +143,51 @@ module RSpec
161
143
 
162
144
  include HashFormatting
163
145
 
146
+ # @private
147
+ module StringEncodingFormatting
148
+ # @api private
149
+ # @return [Boolean] True if the actual and expected string encoding are different.
150
+ # i.e. the failure may be related to encoding differences and the encoding
151
+ # should be shown to the user. false otherwise.
152
+ if String.method_defined?(:encoding)
153
+ def string_encoding_differs?
154
+ actual.is_a?(String) && expected.is_a?(String) && actual.encoding != expected.encoding
155
+ end
156
+ else
157
+ # @api private
158
+ # @return [Boolean] False always as the curent Ruby version does not support String encoding
159
+ # :nocov:
160
+ def string_encoding_differs?
161
+ false
162
+ end
163
+ # :nocov:
164
+ end
165
+ module_function :string_encoding_differs?
166
+
167
+ if String.method_defined?(:encoding)
168
+ # @api private
169
+ # Formats a String's encoding as a human readable string
170
+ # @param value [String]
171
+ # @return [String]
172
+ def format_encoding(value)
173
+ "#<Encoding:#{value.encoding.name}>"
174
+ end
175
+ else
176
+ # @api private
177
+ # Formats a String's encoding as a human readable string
178
+ # @param _value [String]
179
+ # @return [nil] nil as the curent Ruby version does not support String encoding
180
+ # :nocov:
181
+ def format_encoding(_value)
182
+ nil
183
+ end
184
+ # :nocov:
185
+ end
186
+ module_function :format_encoding
187
+ end
188
+
189
+ include StringEncodingFormatting
190
+
164
191
  # @api private
165
192
  # Provides default implementations of failure messages, based on the `description`.
166
193
  module DefaultFailureMessages
@@ -440,9 +440,11 @@ module RSpec
440
440
  Expectations::BlockSnippetExtractor.try_extracting_single_line_body_of(@value_proc, @matcher_name)
441
441
  end
442
442
  else
443
+ # :nocov:
443
444
  def extract_value_block_snippet
444
445
  nil
445
446
  end
447
+ # :nocov:
446
448
  end
447
449
  end
448
450
  end
@@ -51,10 +51,10 @@ module RSpec
51
51
  end
52
52
 
53
53
  # @api private
54
- # @return [RSpec::Matchers::ExpectedsForMultipleDiffs]
54
+ # @return [RSpec::Matchers::MultiMatcherDiff]
55
55
  def expected
56
56
  return nil unless evaluator
57
- ::RSpec::Matchers::ExpectedsForMultipleDiffs.for_many_matchers(diffable_matcher_list)
57
+ ::RSpec::Matchers::MultiMatcherDiff.for_many_matchers(diffable_matcher_list)
58
58
  end
59
59
 
60
60
  protected
@@ -77,8 +77,11 @@ module RSpec
77
77
  def match(_expected, actual)
78
78
  evaluator_klass = if supports_block_expectations? && Proc === actual
79
79
  NestedEvaluator
80
- else
80
+ elsif supports_value_expectations?
81
81
  SequentialEvaluator
82
+ else
83
+ # Can't raise an ArgumentError in this context, as it's rescued
84
+ raise "Block and value matchers can't be combined in a compound expectation (#{matcher_1.description}, #{matcher_2.description})"
82
85
  end
83
86
 
84
87
  @evaluator = evaluator_klass.new(actual, matcher_1, matcher_2)
@@ -171,7 +174,7 @@ module RSpec
171
174
  @match_results.fetch(matcher) do
172
175
  raise ArgumentError, "Your #{matcher.description} has no match " \
173
176
  "results, this can occur when an unexpected call stack or " \
174
- "local jump occurs. Prehaps one of your matchers needs to " \
177
+ "local jump occurs. Perhaps one of your matchers needs to " \
175
178
  "declare `expects_call_stack_jump?` as `true`?"
176
179
  end
177
180
  end
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
- # rubocop:disable ClassLength
4
+ # rubocop:disable Metrics/ClassLength
5
5
  # @api private
6
6
  # Provides the implementation for `contain_exactly` and `match_array`.
7
7
  # Not intended to be instantiated directly.
@@ -31,6 +31,14 @@ module RSpec
31
31
  "contain exactly#{list}"
32
32
  end
33
33
 
34
+ def matches?(actual)
35
+ @pairings_maximizer = nil
36
+ @best_solution = nil
37
+ @extra_items = nil
38
+ @missing_items = nil
39
+ super(actual)
40
+ end
41
+
34
42
  private
35
43
 
36
44
  def generate_failure_message
@@ -100,12 +108,14 @@ module RSpec
100
108
  end
101
109
 
102
110
  if RUBY_VERSION == "1.8.7"
111
+ # :nocov:
103
112
  def to_a_disallowed?(object)
104
113
  case object
105
114
  when NilClass, String then true
106
115
  else Kernel == RSpec::Support.method_handle_for(object, :to_a).owner
107
116
  end
108
117
  end
118
+ # :nocov:
109
119
  else
110
120
  def to_a_disallowed?(object)
111
121
  NilClass === object
@@ -296,7 +306,7 @@ module RSpec
296
306
  end
297
307
  end
298
308
  end
299
- # rubocop:enable ClassLength
309
+ # rubocop:enable Metrics/ClassLength
300
310
  end
301
311
  end
302
312
  end
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  # @api private
5
- # Asbtract class to implement `once`, `at_least` and other
5
+ # Abstract class to implement `once`, `at_least` and other
6
6
  # count constraints.
7
7
  module CountExpectation
8
8
  # @api public
@@ -61,9 +61,11 @@ module RSpec
61
61
  count.cover?(number)
62
62
  end
63
63
  else
64
+ # :nocov:
64
65
  def cover?(count, number)
65
66
  number >= count.first && number <= count.last
66
67
  end
68
+ # :nocov:
67
69
  end
68
70
 
69
71
  def expected_count_matches?(actual_count)
@@ -8,7 +8,11 @@ module RSpec
8
8
  # @api private
9
9
  # @return [String]
10
10
  def failure_message
11
- "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n"
11
+ if string_encoding_differs?
12
+ "\nexpected: #{format_encoding(expected)} #{expected_formatted}\n got: #{format_encoding(actual)} #{actual_formatted}\n\n(compared using ==)\n"
13
+ else
14
+ "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using ==)\n"
15
+ end
12
16
  end
13
17
 
14
18
  # @api private
@@ -8,7 +8,11 @@ module RSpec
8
8
  # @api private
9
9
  # @return [String]
10
10
  def failure_message
11
- "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using eql?)\n"
11
+ if string_encoding_differs?
12
+ "\nexpected: #{format_encoding(expected)} #{expected_formatted}\n got: #{format_encoding(actual)} #{actual_formatted}\n\n(compared using eql?)\n"
13
+ else
14
+ "\nexpected: #{expected_formatted}\n got: #{actual_formatted}\n\n(compared using eql?)\n"
15
+ end
12
16
  end
13
17
 
14
18
  # @api private
@@ -81,7 +81,7 @@ module RSpec
81
81
  end
82
82
 
83
83
  def deprecated(predicate, actual)
84
- predicate == :exists? && File == actual
84
+ predicate == :exists? && (File == actual || FileTest == actual || Dir == actual)
85
85
  end
86
86
  end
87
87
  end
@@ -46,8 +46,27 @@ module RSpec
46
46
 
47
47
  private
48
48
 
49
+ # Catch a semi-frequent typo - if you have strict_predicate_matchers disabled and
50
+ # expect(spy).to have_receieveddd(:foo) it would be evergreen - the dynamic matcher
51
+ # queries `has_receiveddd?`, the spy _fakes_ the method, returning its (truthy) self.
52
+ if defined?(RSpec::Mocks::Double)
53
+ def really_responds_to?(method)
54
+ if RSpec::Mocks::Double === @actual
55
+ @actual.respond_to?(method) && methods_include?(method)
56
+ else
57
+ @actual.respond_to?(method)
58
+ end
59
+ end
60
+ else
61
+ # :nocov:
62
+ def really_responds_to?(method)
63
+ @actual.respond_to?(method)
64
+ end
65
+ # :nocov:
66
+ end
67
+
49
68
  def predicate_accessible?
50
- @actual.respond_to? predicate
69
+ really_responds_to?(predicate)
51
70
  end
52
71
 
53
72
  # support 1.8.7, evaluate once at load time for performance
@@ -56,11 +75,19 @@ module RSpec
56
75
  def private_predicate?
57
76
  @actual.private_methods.include? predicate.to_s
58
77
  end
78
+
79
+ def methods_include?(method)
80
+ @actual.methods.include?(method.to_s)
81
+ end
59
82
  # :nocov:
60
83
  else
61
84
  def private_predicate?
62
85
  @actual.private_methods.include? predicate
63
86
  end
87
+
88
+ def methods_include?(method)
89
+ @actual.methods.include?(method)
90
+ end
64
91
  end
65
92
 
66
93
  def predicate_result
@@ -155,7 +182,7 @@ module RSpec
155
182
  end
156
183
 
157
184
  def predicate_accessible?
158
- super || actual.respond_to?(present_tense_predicate)
185
+ super || really_responds_to?(present_tense_predicate)
159
186
  end
160
187
 
161
188
  def present_tense_predicate
@@ -13,6 +13,7 @@ module RSpec
13
13
 
14
14
  # @api private
15
15
  def initialize(*expecteds)
16
+ raise(ArgumentError, 'include() is not supported, please supply an argument') if expecteds.empty?
16
17
  @expecteds = expecteds
17
18
  end
18
19
 
@@ -153,11 +154,19 @@ module RSpec
153
154
  def actual_hash_has_key?(expected_key)
154
155
  # We check `key?` first for perf:
155
156
  # `key?` is O(1), but `any?` is O(N).
156
- actual.key?(expected_key) ||
157
- actual.keys.any? { |key| values_match?(expected_key, key) }
157
+
158
+ has_exact_key =
159
+ begin
160
+ actual.key?(expected_key)
161
+ rescue
162
+ false
163
+ end
164
+
165
+ has_exact_key || actual.keys.any? { |key| values_match?(expected_key, key) }
158
166
  end
159
167
 
160
168
  def actual_collection_includes?(expected_item)
169
+ return actual.scan(expected_item).size > 0 if Regexp === expected_item && String === actual
161
170
  return true if actual.include?(expected_item)
162
171
 
163
172
  # String lacks an `any?` method...
@@ -167,9 +176,11 @@ module RSpec
167
176
  end
168
177
 
169
178
  if RUBY_VERSION < '1.9'
179
+ # :nocov:
170
180
  def count_enumerable(expected_item)
171
181
  actual.select { |value| values_match?(expected_item, value) }.size
172
182
  end
183
+ # :nocov:
173
184
  else
174
185
  def count_enumerable(expected_item)
175
186
  actual.count { |value| values_match?(expected_item, value) }
@@ -190,6 +201,7 @@ module RSpec
190
201
 
191
202
  def diff_would_wrongly_highlight_matched_item?
192
203
  return false unless actual.is_a?(String) && expected.is_a?(Array)
204
+ return false if Regexp === expecteds.first
193
205
 
194
206
  lines = actual.split("\n")
195
207
  expected.any? do |str|
@@ -78,9 +78,11 @@ module RSpec
78
78
  # @api private
79
79
  # Returns match data names for named captures
80
80
  # @return Array
81
+ # :nocov:
81
82
  def names
82
83
  []
83
84
  end
85
+ # :nocov:
84
86
  else
85
87
  # @api private
86
88
  # Returns match data names for named captures
@@ -4,8 +4,8 @@ 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
8
- # rubocop:disable RescueException
7
+ # rubocop:disable Metrics/ClassLength
8
+ # rubocop:disable Lint/RescueException
9
9
  class RaiseError
10
10
  include Composable
11
11
 
@@ -13,6 +13,10 @@ module RSpec
13
13
  # argument. We can't use `nil` for that because we need to warn when `nil` is
14
14
  # passed in a different way. It's an Object, not a Module, since Module's `===`
15
15
  # does not evaluate to true when compared to itself.
16
+ #
17
+ # Note; this _is_ the default value supplied for expected_error_or_message, but
18
+ # because there are two method-calls involved, that default is actually supplied
19
+ # in the definition of the _matcher_ method, `RSpec::Matchers#raise_error`
16
20
  UndefinedValue = Object.new.freeze
17
21
 
18
22
  def initialize(expected_error_or_message, expected_message, &block)
@@ -25,7 +29,7 @@ module RSpec
25
29
  when nil, UndefinedValue
26
30
  @expected_error = Exception
27
31
  @expected_message = expected_message
28
- when String
32
+ when String, Regexp
29
33
  @expected_error = Exception
30
34
  @expected_message = expected_error_or_message
31
35
  else
@@ -43,7 +47,7 @@ module RSpec
43
47
  self
44
48
  end
45
49
 
46
- # rubocop:disable MethodLength
50
+ # rubocop:disable Metrics/MethodLength
47
51
  # @private
48
52
  def matches?(given_proc, negative_expectation=false, &block)
49
53
  @given_proc = given_proc
@@ -73,7 +77,7 @@ module RSpec
73
77
 
74
78
  expectation_matched?
75
79
  end
76
- # rubocop:enable MethodLength
80
+ # rubocop:enable Metrics/MethodLength
77
81
 
78
82
  # @private
79
83
  def does_not_match?(given_proc)
@@ -264,8 +268,8 @@ module RSpec
264
268
  warning if @actual_error
265
269
  end
266
270
  end
267
- # rubocop:enable RescueException
268
- # rubocop:enable ClassLength
271
+ # rubocop:enable Lint/RescueException
272
+ # rubocop:enable Metrics/ClassLength
269
273
  end
270
274
  end
271
275
  end
@@ -50,9 +50,11 @@ module RSpec
50
50
  Expectations::BlockSnippetExtractor.try_extracting_single_line_body_of(@block, matcher_name)
51
51
  end
52
52
  else
53
+ # :nocov:
53
54
  def block_representation
54
55
  'block'
55
56
  end
57
+ # :nocov:
56
58
  end
57
59
  end
58
60
  end
@@ -13,7 +13,7 @@ module RSpec
13
13
  @caught_symbol = @caught_arg = nil
14
14
  end
15
15
 
16
- # rubocop:disable MethodLength
16
+ # rubocop:disable Metrics/MethodLength
17
17
  # @private
18
18
  def matches?(given_proc)
19
19
  @block = given_proc
@@ -48,7 +48,7 @@ module RSpec
48
48
  rescue => other_exception
49
49
  raise
50
50
  ensure
51
- # rubocop:disable EnsureReturn
51
+ # rubocop:disable Lint/EnsureReturn
52
52
  unless other_exception
53
53
  if @expected_symbol.nil?
54
54
  return !!@caught_symbol
@@ -60,10 +60,10 @@ module RSpec
60
60
  end
61
61
  end
62
62
  end
63
- # rubocop:enable EnsureReturn
63
+ # rubocop:enable Lint/EnsureReturn
64
64
  end
65
65
  end
66
- # rubocop:enable MethodLength
66
+ # rubocop:enable Metrics/MethodLength
67
67
 
68
68
  def does_not_match?(given_proc)
69
69
  !matches?(given_proc) && Proc === given_proc
@@ -83,7 +83,7 @@ module RSpec
83
83
  RSpec::Support::ObjectFormatter.format(object)
84
84
  end
85
85
 
86
- # Transforms the given data structue (typically a hash or array)
86
+ # Transforms the given data structure (typically a hash or array)
87
87
  # into a new data structure that, when `#inspect` is called on it,
88
88
  # will provide descriptions of any contained matchers rather than
89
89
  # the normal `#inspect` output.
@@ -4,7 +4,7 @@ module RSpec
4
4
  module Matchers
5
5
  # Defines the custom matcher DSL.
6
6
  module DSL
7
- # Defines a matcher alias. The returned matcher's `description` will be overriden
7
+ # Defines a matcher alias. The returned matcher's `description` will be overridden
8
8
  # to reflect the phrasing of the new name, which will be used in failure messages
9
9
  # when passed as an argument to another matcher in a composed matcher expression.
10
10
  #
@@ -25,7 +25,7 @@ module RSpec
25
25
  # @param old_name [Symbol] the original name for the matcher
26
26
  # @param options [Hash] options for the aliased matcher
27
27
  # @option options [Class] :klass the ruby class to use as the decorator. (Not normally used).
28
- # @yield [String] optional block that, when given, is used to define the overriden
28
+ # @yield [String] optional block that, when given, is used to define the overridden
29
29
  # logic. The yielded arg is the original description or failure message. If no
30
30
  # block is provided, a default override is used based on the old and new names.
31
31
  # @see RSpec::Matchers
@@ -40,10 +40,11 @@ module RSpec
40
40
  matcher.matcher_name = new_name if matcher.respond_to?(:matcher_name=)
41
41
  klass.new(matcher, description_override)
42
42
  end
43
+ ruby2_keywords new_name if respond_to?(:ruby2_keywords, true)
43
44
  end
44
45
 
45
46
  # Defines a negated matcher. The returned matcher's `description` and `failure_message`
46
- # will be overriden to reflect the phrasing of the new name, and the match logic will
47
+ # will be overridden to reflect the phrasing of the new name, and the match logic will
47
48
  # be based on the original matcher but negated.
48
49
  #
49
50
  # @example
@@ -53,7 +54,7 @@ module RSpec
53
54
  #
54
55
  # @param negated_name [Symbol] the name for the negated matcher
55
56
  # @param base_name [Symbol] the name of the original matcher that will be negated
56
- # @yield [String] optional block that, when given, is used to define the overriden
57
+ # @yield [String] optional block that, when given, is used to define the overridden
57
58
  # logic. The yielded arg is the original description or failure message. If no
58
59
  # block is provided, a default override is used based on the old and new names.
59
60
  # @see RSpec::Matchers
@@ -122,7 +123,7 @@ module RSpec
122
123
  #
123
124
  # By default the match block will swallow expectation errors (e.g.
124
125
  # caused by using an expectation such as `expect(1).to eq 2`), if you
125
- # with to allow these to bubble up, pass in the option
126
+ # wish to allow these to bubble up, pass in the option
126
127
  # `:notify_expectation_failures => true`.
127
128
  #
128
129
  # @param [Hash] options for defining the behavior of the match block.
@@ -151,7 +152,7 @@ module RSpec
151
152
  #
152
153
  # By default the match block will swallow expectation errors (e.g.
153
154
  # caused by using an expectation such as `expect(1).to eq 2`), if you
154
- # with to allow these to bubble up, pass in the option
155
+ # wish to allow these to bubble up, pass in the option
155
156
  # `:notify_expectation_failures => true`.
156
157
  #
157
158
  # @param [Hash] options for defining the behavior of the match block.
@@ -197,7 +198,7 @@ module RSpec
197
198
  end
198
199
  end
199
200
 
200
- # Customizes the failure messsage to use when this matcher is
201
+ # Customizes the failure message to use when this matcher is
201
202
  # asked to positively match. Only use this when the message
202
203
  # generated by default doesn't suit your needs.
203
204
  #
@@ -216,7 +217,7 @@ module RSpec
216
217
  define_user_override(__method__, definition)
217
218
  end
218
219
 
219
- # Customize the failure messsage to use when this matcher is asked
220
+ # Customize the failure message to use when this matcher is asked
220
221
  # to negatively match. Only use this when the message generated by
221
222
  # default doesn't suit your needs.
222
223
  #
@@ -330,7 +331,7 @@ module RSpec
330
331
  # - Defines the named method using a user-provided block
331
332
  # in @user_method_defs, which is included as an ancestor
332
333
  # in the singleton class in which we eval the `define` block.
333
- # - Defines an overriden definition for the same method
334
+ # - Defines an overridden definition for the same method
334
335
  # usign the provided `our_def` block.
335
336
  # - Provides a default `our_def` block for the common case
336
337
  # of needing to call the user's definition with `@actual`
@@ -45,12 +45,14 @@ module RSpec
45
45
  # So here we replace `Kernel#Array` with our own warning-free implementation for 1.8.7.
46
46
  # @private
47
47
  # rubocop:disable Naming/MethodName
48
+ # :nocov:
48
49
  def self.Array(obj)
49
50
  case obj
50
51
  when Array then obj
51
52
  else [obj]
52
53
  end
53
54
  end
55
+ # :nocov:
54
56
  # rubocop:enable Naming/MethodName
55
57
  end
56
58
  end
@@ -1,8 +1,34 @@
1
1
  module RSpec
2
2
  module Matchers
3
+ # Provides a base class with as little methods as possible, so that
4
+ # most methods can be delegated via `method_missing`.
5
+ #
6
+ # On Ruby 2.0+ BasicObject could be used for this purpose, but it
7
+ # introduce some extra complexity with constant resolution, so the
8
+ # BlankSlate pattern was prefered.
9
+ # @private
10
+ class BaseDelegator
11
+ kept_methods = [
12
+ # Methods that raise warnings if removed.
13
+ :__id__, :__send__, :object_id,
14
+
15
+ # Methods that are explicitly undefined in some subclasses.
16
+ :==, :===,
17
+
18
+ # Methods we keep on purpose.
19
+ :class, :respond_to?, :__method__, :method, :dup,
20
+ :clone, :initialize_dup, :initialize_copy, :initialize_clone,
21
+ ]
22
+ instance_methods.each do |method|
23
+ unless kept_methods.include?(method.to_sym)
24
+ undef_method(method)
25
+ end
26
+ end
27
+ end
28
+
3
29
  # Provides the necessary plumbing to wrap a matcher with a decorator.
4
30
  # @private
5
- class MatcherDelegator
31
+ class MatcherDelegator < BaseDelegator
6
32
  include Composable
7
33
  attr_reader :base_matcher
8
34
 
@@ -1,9 +1,9 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  # @api private
4
- # Handles list of expected values when there is a need to render
5
- # multiple diffs. Also can handle one value.
6
- class ExpectedsForMultipleDiffs
4
+ # Handles list of expected and actual value pairs when there is a need
5
+ # to render multiple diffs. Also can handle one pair.
6
+ class MultiMatcherDiff
7
7
  # @private
8
8
  # Default diff label when there is only one matcher in diff
9
9
  # output
@@ -19,22 +19,23 @@ module RSpec
19
19
 
20
20
  # @api private
21
21
  # Wraps provided expected value in instance of
22
- # ExpectedForMultipleDiffs. If provided value is already an
23
- # ExpectedForMultipleDiffs then it just returns it.
22
+ # MultiMatcherDiff. If provided value is already an
23
+ # MultiMatcherDiff then it just returns it.
24
24
  # @param [Any] expected value to be wrapped
25
- # @return [RSpec::Matchers::ExpectedsForMultipleDiffs]
26
- def self.from(expected)
25
+ # @param [Any] actual value
26
+ # @return [RSpec::Matchers::MultiMatcherDiff]
27
+ def self.from(expected, actual)
27
28
  return expected if self === expected
28
- new([[expected, DEFAULT_DIFF_LABEL]])
29
+ new([[expected, DEFAULT_DIFF_LABEL, actual]])
29
30
  end
30
31
 
31
32
  # @api private
32
33
  # Wraps provided matcher list in instance of
33
- # ExpectedForMultipleDiffs.
34
+ # MultiMatcherDiff.
34
35
  # @param [Array<Any>] matchers list of matchers to wrap
35
- # @return [RSpec::Matchers::ExpectedsForMultipleDiffs]
36
+ # @return [RSpec::Matchers::MultiMatcherDiff]
36
37
  def self.for_many_matchers(matchers)
37
- new(matchers.map { |m| [m.expected, diff_label_for(m)] })
38
+ new(matchers.map { |m| [m.expected, diff_label_for(m), m.actual] })
38
39
  end
39
40
 
40
41
  # @api private
@@ -42,10 +43,9 @@ module RSpec
42
43
  # factory and actual value if there are any
43
44
  # @param [String] message original failure message
44
45
  # @param [Proc] differ
45
- # @param [Any] actual value
46
46
  # @return [String]
47
- def message_with_diff(message, differ, actual)
48
- diff = diffs(differ, actual)
47
+ def message_with_diff(message, differ)
48
+ diff = diffs(differ)
49
49
  message = "#{message}\n#{diff}" unless diff.empty?
50
50
  message
51
51
  end
@@ -65,8 +65,8 @@ module RSpec
65
65
  end
66
66
  end
67
67
 
68
- def diffs(differ, actual)
69
- @expected_list.map do |(expected, diff_label)|
68
+ def diffs(differ)
69
+ @expected_list.map do |(expected, diff_label, actual)|
70
70
  diff = differ.diff(actual, expected)
71
71
  next if diff.strip.empty?
72
72
  if diff == "\e[0m\n\e[0m"
@@ -10,7 +10,7 @@ RSpec::Support.define_optimized_require_for_rspec(:matchers) { |f| require_relat
10
10
  dsl
11
11
  matcher_delegator
12
12
  aliased_matcher
13
- expecteds_for_multiple_diffs
13
+ multi_matcher_diff
14
14
  ].each { |file| RSpec::Support.require_rspec_matchers(file) }
15
15
 
16
16
  # RSpec's top level namespace. All of rspec-expectations is contained
@@ -36,7 +36,7 @@ module RSpec
36
36
  # expect([]).to be_empty # => [].empty?() | passes
37
37
  # expect([]).not_to be_empty # => [].empty?() | fails
38
38
  #
39
- # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_"
39
+ # In addition to prefixing the predicate matchers with "be_", you can also use "be_a_"
40
40
  # and "be_an_", making your specs read much more naturally:
41
41
  #
42
42
  # expect("a string").to be_an_instance_of(String) # =>"a string".instance_of?(String) # passes
@@ -704,7 +704,7 @@ module RSpec
704
704
 
705
705
  # An alternate form of `contain_exactly` that accepts
706
706
  # the expected contents as a single array arg rather
707
- # that splatted out as individual items.
707
+ # than splatted out as individual items.
708
708
  #
709
709
  # @example
710
710
  # expect(results).to contain_exactly(1, 2)
@@ -715,6 +715,9 @@ module RSpec
715
715
  def match_array(items)
716
716
  contain_exactly(*items)
717
717
  end
718
+ alias_matcher :an_array_matching, :match_array do |desc|
719
+ desc.sub("contain exactly", "an array containing exactly")
720
+ end
718
721
 
719
722
  # With no arg, passes if the block outputs `to_stdout` or `to_stderr`.
720
723
  # With a string, passes if the block outputs that specific string `to_stdout` or `to_stderr`.
@@ -753,8 +756,8 @@ module RSpec
753
756
 
754
757
  # With no args, matches if any error is raised.
755
758
  # With a named error, matches only if that specific error is raised.
756
- # With a named error and messsage specified as a String, matches only if both match.
757
- # With a named error and messsage specified as a Regexp, matches only if both match.
759
+ # With a named error and message specified as a String, matches only if both match.
760
+ # With a named error and message specified as a Regexp, matches only if both match.
758
761
  # Pass an optional block to perform extra verifications on the exception matched
759
762
  #
760
763
  # @example
@@ -1015,6 +1018,7 @@ module RSpec
1015
1018
  # than _before_, like `append_features`. It's important we check this before
1016
1019
  # in order to find the cases where it was already previously included.
1017
1020
  # @api private
1021
+ # :nocov:
1018
1022
  def append_features(mod)
1019
1023
  return super if mod < self # `mod < self` indicates a re-inclusion.
1020
1024
 
@@ -1035,6 +1039,7 @@ module RSpec
1035
1039
 
1036
1040
  super
1037
1041
  end
1042
+ # :nocov:
1038
1043
  end
1039
1044
  end
1040
1045
  end
data.tar.gz.sig CHANGED
Binary file
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.11.0
4
+ version: 3.13.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Baker
@@ -45,7 +45,7 @@ cert_chain:
45
45
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
46
46
  F3MdtaDehhjC
47
47
  -----END CERTIFICATE-----
48
- date: 2022-02-09 00:00:00.000000000 Z
48
+ date: 2024-09-07 00:00:00.000000000 Z
49
49
  dependencies:
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: rspec-support
@@ -53,14 +53,14 @@ dependencies:
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: 3.11.0
56
+ version: 3.13.0
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - "~>"
62
62
  - !ruby/object:Gem::Version
63
- version: 3.11.0
63
+ version: 3.13.0
64
64
  - !ruby/object:Gem::Dependency
65
65
  name: diff-lcs
66
66
  requirement: !ruby/object:Gem::Requirement
@@ -193,17 +193,17 @@ files:
193
193
  - lib/rspec/matchers/composable.rb
194
194
  - lib/rspec/matchers/dsl.rb
195
195
  - lib/rspec/matchers/english_phrasing.rb
196
- - lib/rspec/matchers/expecteds_for_multiple_diffs.rb
197
196
  - lib/rspec/matchers/fail_matchers.rb
198
197
  - lib/rspec/matchers/generated_descriptions.rb
199
198
  - lib/rspec/matchers/matcher_delegator.rb
200
199
  - lib/rspec/matchers/matcher_protocol.rb
200
+ - lib/rspec/matchers/multi_matcher_diff.rb
201
201
  homepage: https://github.com/rspec/rspec-expectations
202
202
  licenses:
203
203
  - MIT
204
204
  metadata:
205
205
  bug_tracker_uri: https://github.com/rspec/rspec-expectations/issues
206
- changelog_uri: https://github.com/rspec/rspec-expectations/blob/v3.11.0/Changelog.md
206
+ changelog_uri: https://github.com/rspec/rspec-expectations/blob/v3.13.3/Changelog.md
207
207
  documentation_uri: https://rspec.info/documentation/
208
208
  mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
209
209
  source_code_uri: https://github.com/rspec/rspec-expectations
@@ -223,8 +223,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
223
  - !ruby/object:Gem::Version
224
224
  version: '0'
225
225
  requirements: []
226
- rubygems_version: 3.3.3
226
+ rubygems_version: 3.4.19
227
227
  signing_key:
228
228
  specification_version: 4
229
- summary: rspec-expectations-3.11.0
229
+ summary: rspec-expectations-3.13.3
230
230
  test_files: []
metadata.gz.sig CHANGED
Binary file