rspec-support 3.13.7 → 4.0.0.beta1

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: ced51c215b6d9b3af8f27d1abe6033a633f3818312c1bd5850195a10e1ccb172
4
- data.tar.gz: dd7afad96ac46be53ad3df4956098a7ec936828c67acb2446f9d5fa37d0bc940
3
+ metadata.gz: cc1363792fc66b3235686119b09af82568e6ab339f0cdd2835e92988f8693024
4
+ data.tar.gz: a375231249ed4d4b3b8b0d2a96e57f25497361aa048c5d850bcf80c12422ad21
5
5
  SHA512:
6
- metadata.gz: '0996fd67d068112ba314ac10665a6bbc8b0c2a9c56e2147008bcf38d589de944023a27776b88f496388fb862e8f6dfa8efae4e45066f03f3672060ebfd58deb8'
7
- data.tar.gz: 052d7bf8afb92561f555026534c8380f276aabdc0abab2572beb31788b4505e72080a8cb1179ad8c828fb4ed9fe65b5c9ccb8566d13d519c6aae4996b124caa4
6
+ metadata.gz: e234899c929288a0a1908133573bb90225430716a58ec1fc4d63ac11a1603dde06db862dd536a490d0a35f833feaf6afc0afe7f6e7533fa18f8cdfc6f42647b3
7
+ data.tar.gz: 7d20632c52abfac745d28100ef5d41449c05bfdf97a78ee2723a73d2c3d13129cf24794cfc581e7bc4c5b4f1085556ad0d0613f1847d27ef39295552e6bf683e
checksums.yaml.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,11 +1,32 @@
1
1
  ### Development
2
- [Full Changelog](https://github.com/rspec/rspec/compare/rspec-support-v3.13.6...3-13-maintenance)
2
+ [Full Changelog](https://github.com/rspec/rspec/compare/rspec-support-v3.13.6...main)
3
+
4
+ # 4.0.0.beta1 / 2026-02-18
5
+
6
+ Breaking Changes:
7
+
8
+ * Ruby < 3.0 is no longer supported. (Phil Pirozhkov, Jon Rowe, rspec/rspec-support#436, rspec/rspec#258)
9
+ * Removed unused `RSpec::Support::ObjectFormatter::BigDecimalInspector`. (Jon Rowe, rspec/rspec#254)
10
+ * Remove unsupported `RSpec::Support::RubyFeatures.supports_taint?` check. (Jon Rowe, rspec/rspec#255)
11
+ * Remove unsupported `RSpec::Support::RubyFeatures.kw_arg_separation?` check. (Jon Rowe, rspec/rspec#256)
12
+ * Remove unsupported `RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash?` check. (Jon Rowe, rspec/rspec#257)
13
+
14
+ Enhancements
15
+
16
+ * Improve diff for `anything` matchers by hiding the value "anything" is matched
17
+ against. (Karl Heitmann, rspec/rspec-mocks#599)
18
+
19
+ Bug Fixes:
20
+
21
+ * Switch current thread data to alias/accessors to avoid issues with mocked systems.
22
+ (Jon Rowe, #610)
23
+ * Always return a boolean from `RSpec::Support::Ruby.rbx?` and
24
+ `RSpec::Support::Ruby.truffleruby?` (Phil Pirozhkov, rspec/rspec-support#486)
3
25
 
4
26
  ### 3.13.7 / 2026-01-28
5
27
  [Full Changelog](http://github.com/rspec/rspec/compare/rspec-support-v3.13.6...rspec-support-v3.13.7)
6
28
 
7
29
  Bug Fixes:
8
-
9
30
  * Stop fuzzy matching causing false positives from Range objects. (Eric Mueller, rspec/rspec#298)
10
31
 
11
32
  ### 3.13.6 / 2025-08-18
data/LICENSE.md CHANGED
@@ -1,7 +1,10 @@
1
1
  The MIT License (MIT)
2
- ====================
2
+ =====================
3
3
 
4
4
  * Copyright © 2013 David Chelimsky, Myron Marston, Jon Rowe, Sam Phippen, Xavier Shay, Bradley Schaefer
5
+ * Copyright © 2012 David Chelimsky, Myron Marston
6
+ * Copyright © 2006 David Chelimsky, The RSpec Development Team
7
+ * Copyright © 2005 Steven Baker
5
8
 
6
9
  Permission is hereby granted, free of charge, to any person obtaining
7
10
  a copy of this software and associated documentation files (the
@@ -16,8 +19,8 @@ included in all copies or substantial portions of the Software.
16
19
 
17
20
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
21
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,40 +1,8 @@
1
- # RSpec::Support [![Build Status](https://github.com/rspec/rspec-support/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-support/actions)
1
+ # RSpec::Support
2
2
 
3
- `RSpec::Support` provides common functionality to `RSpec::Core`,
4
- `RSpec::Expectations` and `RSpec::Mocks`. It is considered
5
- suitable for internal use only at this time.
3
+ This is the readme for `rspec-support`, there isn't anything to see here but see also:
6
4
 
7
- ## Installation / Usage
8
-
9
- Install one or more of the `RSpec` gems.
10
-
11
- Want to run against the `main` branch? You'll need to include the dependent
12
- RSpec repos as well. Add the following to your `Gemfile`:
13
-
14
- ```ruby
15
- %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
16
- gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'main'
17
- end
18
- ```
19
-
20
- ## Contributing
21
-
22
- Once you've set up the environment, you'll need to cd into the working
23
- directory of whichever repo you want to work in. From there you can run the
24
- specs and cucumber features, and make patches.
25
-
26
- NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You
27
- can treat each RSpec repo as an independent project.
28
-
29
- - [Build details](BUILD_DETAIL.md)
30
- - [Code of Conduct](CODE_OF_CONDUCT.md)
31
- - [Detailed contributing guide](CONTRIBUTING.md)
32
- - [Development setup guide](DEVELOPMENT.md)
33
-
34
- ## Patches
35
-
36
- Please submit a pull request or a github issue. If you submit an issue, please
37
- include a link to either of:
38
-
39
- * a gist (or equivalent) of the patch
40
- * a branch or commit in your github fork of the repo
5
+ * [The combined readme](../README.md)
6
+ * [rspec-core](../rspec-core/README.md)
7
+ * [rspec-expectations](../rspec-expectations/README.md)
8
+ * [rspec-mocks](../rspec-mocks/README.md)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec::Support.require_rspec_support "ruby_features"
4
-
5
3
  module RSpec
6
4
  # Consistent implementation for "cleaning" the caller method to strip out
7
5
  # non-rspec lines. This enables errors to be reported at the call site in
@@ -29,56 +27,47 @@ module RSpec
29
27
  # with this complexity in our `RSpec.deprecate` calls, so we ignore it here.
30
28
  IGNORE_REGEX = Regexp.union(LIB_REGEX, "rubygems/core_ext/kernel_require.rb", "<internal:", %r{/lib/ruby/[^/]+/bundled_gems\.rb})
31
29
 
32
- if RSpec::Support::RubyFeatures.caller_locations_supported?
33
- # This supports args because it's more efficient when the caller specifies
34
- # these. It allows us to skip frames the caller knows are part of RSpec,
35
- # and to decrease the increment size if the caller is confident the line will
36
- # be found in a small number of stack frames from `skip_frames`.
37
- #
38
- # Note that there is a risk to passing a `skip_frames` value that is too high:
39
- # If it skipped the first non-rspec line, then this method would return the
40
- # 2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass
41
- # values for these parameters, particularly since most places that use this are
42
- # not hot spots (generally it gets used for deprecation warnings). However,
43
- # if you do have a hot spot that calls this, passing `skip_frames` can make
44
- # a significant difference. Just make sure that that particular use is tested
45
- # so that if the provided `skip_frames` changes to no longer be accurate in
46
- # such a way that would return the wrong stack frame, a test will fail to tell you.
47
- #
48
- # See benchmarks/skip_frames_for_caller_filter.rb for measurements.
49
- def self.first_non_rspec_line(skip_frames=3, increment=5)
50
- # Why a default `skip_frames` of 3?
51
- # By the time `caller_locations` is called below, the first 3 frames are:
52
- # lib/rspec/support/caller_filter.rb:63:in `block in first_non_rspec_line'
53
- # lib/rspec/support/caller_filter.rb:62:in `loop'
54
- # lib/rspec/support/caller_filter.rb:62:in `first_non_rspec_line'
30
+ # This supports args because it's more efficient when the caller specifies
31
+ # these. It allows us to skip frames the caller knows are part of RSpec,
32
+ # and to decrease the increment size if the caller is confident the line will
33
+ # be found in a small number of stack frames from `skip_frames`.
34
+ #
35
+ # Note that there is a risk to passing a `skip_frames` value that is too high:
36
+ # If it skipped the first non-rspec line, then this method would return the
37
+ # 2nd or 3rd (or whatever) non-rspec line. Thus, you generally shouldn't pass
38
+ # values for these parameters, particularly since most places that use this are
39
+ # not hot spots (generally it gets used for deprecation warnings). However,
40
+ # if you do have a hot spot that calls this, passing `skip_frames` can make
41
+ # a significant difference. Just make sure that that particular use is tested
42
+ # so that if the provided `skip_frames` changes to no longer be accurate in
43
+ # such a way that would return the wrong stack frame, a test will fail to tell you.
44
+ #
45
+ # See benchmarks/skip_frames_for_caller_filter.rb for measurements.
46
+ def self.first_non_rspec_line(skip_frames=3, increment=5)
47
+ # Why a default `skip_frames` of 3?
48
+ # By the time `caller_locations` is called below, the first 3 frames are:
49
+ # lib/rspec/support/caller_filter.rb:63:in `block in first_non_rspec_line'
50
+ # lib/rspec/support/caller_filter.rb:62:in `loop'
51
+ # lib/rspec/support/caller_filter.rb:62:in `first_non_rspec_line'
55
52
 
56
- # `caller` is an expensive method that scales linearly with the size of
57
- # the stack. The performance hit for fetching it in chunks is small,
58
- # and since the target line is probably near the top of the stack, the
59
- # overall improvement of a chunked search like this is significant.
60
- #
61
- # See benchmarks/caller.rb for measurements.
53
+ # `caller` is an expensive method that scales linearly with the size of
54
+ # the stack. The performance hit for fetching it in chunks is small,
55
+ # and since the target line is probably near the top of the stack, the
56
+ # overall improvement of a chunked search like this is significant.
57
+ #
62
58
 
63
- # The default increment of 5 for this method are mostly arbitrary, but
64
- # is chosen to give good performance on the common case of creating a double.
59
+ # The default increment of 5 for this method are mostly arbitrary, but
60
+ # is chosen to give good performance on the common case of creating a double.
65
61
 
66
- loop do
67
- stack = caller_locations(skip_frames, increment)
68
- raise "No non-lib lines in stack" unless stack
62
+ loop do
63
+ stack = caller_locations(skip_frames, increment)
64
+ raise "No non-lib lines in stack" unless stack
69
65
 
70
- line = stack.find { |l| l.path !~ IGNORE_REGEX }
71
- return line.to_s if line
66
+ line = stack.find { |l| l.path !~ IGNORE_REGEX }
67
+ return line.to_s if line
72
68
 
73
- skip_frames += increment
74
- increment *= 2 # The choice of two here is arbitrary.
75
- end
76
- end
77
- else
78
- # Earlier rubies do not support the two argument form of `caller`. This
79
- # fallback is logically the same, but slower.
80
- def self.first_non_rspec_line(*)
81
- caller.find { |line| line !~ IGNORE_REGEX }
69
+ skip_frames += increment
70
+ increment *= 2 # The choice of two here is arbitrary.
82
71
  end
83
72
  end
84
73
  end
@@ -17,6 +17,8 @@ module RSpec
17
17
  if any_multiline_strings?(actual, expected)
18
18
  diff = diff_as_string(coerce_to_string(actual), coerce_to_string(expected))
19
19
  end
20
+ elsif all_hashes?(actual, expected)
21
+ diff = diff_hashes_as_object(actual, expected)
20
22
  elsif no_procs?(actual, expected) && no_numbers?(actual, expected)
21
23
  diff = diff_as_object(actual, expected)
22
24
  end
@@ -55,6 +57,25 @@ module RSpec
55
57
  end
56
58
  # rubocop:enable Metrics/MethodLength
57
59
 
60
+ if defined?(RSpec::Mocks::ArgumentMatchers::AnyArgMatcher)
61
+ def diff_hashes_as_object(actual, expected)
62
+ actual_to_diff =
63
+ actual.keys.reduce({}) do |hash, key|
64
+ if RSpec::Mocks::ArgumentMatchers::AnyArgMatcher === expected[key]
65
+ hash[key] = expected[key]
66
+ else
67
+ hash[key] = actual[key]
68
+ end
69
+ hash
70
+ end
71
+ diff_as_object(actual_to_diff, expected)
72
+ end
73
+ else
74
+ def diff_hashes_as_object(actual, expected)
75
+ diff_as_object(actual, expected)
76
+ end
77
+ end
78
+
58
79
  def diff_as_object(actual, expected)
59
80
  actual_as_string = object_to_string(actual)
60
81
  expected_as_string = object_to_string(expected)
@@ -76,6 +97,10 @@ module RSpec
76
97
  safely_flatten(args).none? { |a| Proc === a }
77
98
  end
78
99
 
100
+ def all_hashes?(actual, expected)
101
+ (Hash === actual) && (Hash === expected)
102
+ end
103
+
79
104
  def all_strings?(*args)
80
105
  safely_flatten(args).all? { |a| String === a }
81
106
  end
@@ -103,14 +128,8 @@ module RSpec
103
128
  end
104
129
  end
105
130
 
106
- if String.method_defined?(:encoding)
107
- def multiline?(string)
108
- string.include?("\n".encode(string.encoding))
109
- end
110
- else
111
- def multiline?(string)
112
- string.include?("\n")
113
- end
131
+ def multiline?(string)
132
+ string.include?("\n".encode(string.encoding))
114
133
  end
115
134
 
116
135
  def build_hunks(actual, expected)
@@ -201,13 +220,13 @@ module RSpec
201
220
  end
202
221
 
203
222
  def handle_encoding_errors(actual, expected)
204
- if actual.source_encoding != expected.source_encoding
205
- "Could not produce a diff because the encoding of the actual string " \
206
- "(#{actual.source_encoding}) differs from the encoding of the expected " \
207
- "string (#{expected.source_encoding})"
208
- else
223
+ if actual.source_encoding == expected.source_encoding
209
224
  "Could not produce a diff because of the encoding of the string " \
210
- "(#{expected.source_encoding})"
225
+ "(#{expected.source_encoding})"
226
+ else
227
+ "Could not produce a diff because the encoding of the actual string " \
228
+ "(#{actual.source_encoding}) differs from the encoding of the expected " \
229
+ "string (#{expected.source_encoding})"
211
230
  end
212
231
  end
213
232
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec::Support.require_rspec_support 'ruby_features'
4
-
5
3
  module RSpec
6
4
  module Support
7
5
  # @api private
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ RSpec::Support.require_rspec_support "ruby_features"
3
4
  module RSpec
4
5
  module Support
5
6
  # @private
@@ -13,6 +14,10 @@ module RSpec
13
14
  # ? ("\x3F")
14
15
  REPLACE = "?"
15
16
 
17
+ def self.pick_encoding(source_a, source_b)
18
+ Encoding.compatible?(source_a, source_b) || Encoding.default_external
19
+ end
20
+
16
21
  def initialize(string, encoding=nil)
17
22
  @encoding = encoding
18
23
  @source_encoding = detect_source_encoding(string)
@@ -48,12 +53,50 @@ module RSpec
48
53
  end
49
54
  alias :to_str :to_s
50
55
 
51
- if String.method_defined?(:encoding)
52
-
53
- private
54
-
55
- # Encoding Exceptions:
56
- #
56
+ private
57
+
58
+ # Encoding Exceptions:
59
+ #
60
+ # Raised by Encoding and String methods:
61
+ # Encoding::UndefinedConversionError:
62
+ # when a transcoding operation fails
63
+ # if the String contains characters invalid for the target encoding
64
+ # e.g. "\x80".encode('UTF-8','ASCII-8BIT')
65
+ # vs "\x80".encode('UTF-8','ASCII-8BIT', undef: :replace, replace: '<undef>')
66
+ # # => '<undef>'
67
+ # Encoding::CompatibilityError
68
+ # when Encoding.compatible?(str1, str2) is nil
69
+ # e.g. utf_16le_emoji_string.split("\n")
70
+ # e.g. valid_unicode_string.encode(utf8_encoding) << ascii_string
71
+ # Encoding::InvalidByteSequenceError:
72
+ # when the string being transcoded contains a byte invalid for
73
+ # either the source or target encoding
74
+ # e.g. "\x80".encode('UTF-8','US-ASCII')
75
+ # vs "\x80".encode('UTF-8','US-ASCII', invalid: :replace, replace: '<byte>')
76
+ # # => '<byte>'
77
+ # ArgumentError
78
+ # when operating on a string with invalid bytes
79
+ # e.g."\x80".split("\n")
80
+ # TypeError
81
+ # when a symbol is passed as an encoding
82
+ # Encoding.find(:"UTF-8")
83
+ # when calling force_encoding on an object
84
+ # that doesn't respond to #to_str
85
+ #
86
+ # Raised by transcoding methods:
87
+ # Encoding::ConverterNotFoundError:
88
+ # when a named encoding does not correspond with a known converter
89
+ # e.g. 'abc'.force_encoding('UTF-8').encode('foo')
90
+ # or a converter path cannot be found
91
+ # e.g. "\x80".force_encoding('ASCII-8BIT').encode('Emacs-Mule')
92
+ #
93
+ # Raised by byte <-> char conversions
94
+ # RangeError: out of char range
95
+ # e.g. the UTF-16LE emoji: 128169.chr
96
+ def matching_encoding(string)
97
+ string = remove_invalid_bytes(string)
98
+ string.encode(@encoding)
99
+ rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
57
100
  # Raised by Encoding and String methods:
58
101
  # Encoding::UndefinedConversionError:
59
102
  # when a transcoding operation fails
@@ -80,83 +123,23 @@ module RSpec
80
123
  # when calling force_encoding on an object
81
124
  # that doesn't respond to #to_str
82
125
  #
83
- # Raised by transcoding methods:
84
- # Encoding::ConverterNotFoundError:
85
- # when a named encoding does not correspond with a known converter
86
- # e.g. 'abc'.force_encoding('UTF-8').encode('foo')
87
- # or a converter path cannot be found
88
- # e.g. "\x80".force_encoding('ASCII-8BIT').encode('Emacs-Mule')
126
+ # For example, given:
127
+ # "\x80".force_encoding("Emacs-Mule").encode(:invalid => :replace).bytes.to_a
89
128
  #
90
- # Raised by byte <-> char conversions
91
- # RangeError: out of char range
92
- # e.g. the UTF-16LE emoji: 128169.chr
93
- def matching_encoding(string)
94
- string = remove_invalid_bytes(string)
95
- string.encode(@encoding)
96
- rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
97
- # Originally defined as a constant to avoid unneeded allocations, this hash must
98
- # be defined inline (without {}) to avoid warnings on Ruby 2.7
99
- #
100
- # In MRI 2.1 'invalid: :replace' changed to also replace an invalid byte sequence
101
- # see https://github.com/ruby/ruby/blob/v2_1_0/NEWS#L176
102
- # https://www.ruby-forum.com/topic/6861247
103
- # https://twitter.com/nalsh/status/553413844685438976
104
- #
105
- # For example, given:
106
- # "\x80".force_encoding("Emacs-Mule").encode(:invalid => :replace).bytes.to_a
107
- #
108
- # On MRI 2.1 or above: 63 # '?'
109
- # else : 128 # "\x80"
110
- #
111
- string.encode(@encoding, :invalid => :replace, :undef => :replace, :replace => REPLACE)
112
- rescue Encoding::ConverterNotFoundError
113
- # Originally defined as a constant to avoid unneeded allocations, this hash must
114
- # be defined inline (without {}) to avoid warnings on Ruby 2.7
115
- string.dup.force_encoding(@encoding).encode(:invalid => :replace, :replace => REPLACE)
116
- end
117
-
118
- # Prevents raising ArgumentError
119
- if String.method_defined?(:scrub)
120
- # https://github.com/ruby/ruby/blob/eeb05e8c11/doc/NEWS-2.1.0#L120-L123
121
- # https://github.com/ruby/ruby/blob/v2_1_0/string.c#L8242
122
- # https://github.com/hsbt/string-scrub
123
- # https://github.com/rubinius/rubinius/blob/v2.5.2/kernel/common/string.rb#L1913-L1972
124
- def remove_invalid_bytes(string)
125
- string.scrub(REPLACE)
126
- end
127
- else
128
- # http://stackoverflow.com/a/8711118/879854
129
- # Loop over chars in a string replacing chars
130
- # with invalid encoding, which is a pretty good proxy
131
- # for the invalid byte sequence that causes an ArgumentError
132
- def remove_invalid_bytes(string)
133
- string.chars.map do |char|
134
- char.valid_encoding? ? char : REPLACE
135
- end.join
136
- end
137
- end
138
-
139
- def detect_source_encoding(string)
140
- string.encoding
141
- end
142
-
143
- def self.pick_encoding(source_a, source_b)
144
- Encoding.compatible?(source_a, source_b) || Encoding.default_external
145
- end
146
- else
147
-
148
- def self.pick_encoding(_source_a, _source_b)
149
- end
150
-
151
- private
129
+ # On MRI 2.1 or above: 63 # '?'
130
+ # else : 128 # "\x80"
131
+ #
132
+ string.encode(@encoding, :invalid => :replace, :undef => :replace, :replace => REPLACE)
133
+ rescue Encoding::ConverterNotFoundError
134
+ string.dup.force_encoding(@encoding).encode(:invalid => :replace, :replace => REPLACE)
135
+ end
152
136
 
153
- def matching_encoding(string)
154
- string
155
- end
137
+ def remove_invalid_bytes(string)
138
+ string.scrub(REPLACE)
139
+ end
156
140
 
157
- def detect_source_encoding(_string)
158
- US_ASCII
159
- end
141
+ def detect_source_encoding(string)
142
+ string.encoding
160
143
  end
161
144
  end
162
145
  end
@@ -22,8 +22,7 @@ module RSpec
22
22
  begin
23
23
  expected === actual
24
24
  rescue ArgumentError
25
- # Some objects, like 0-arg lambdas on 1.9+, raise
26
- # ArgumentError for `expected === actual`.
25
+ # Some objects, like 0-arg lambdas, raise ArgumentError when compared with ===.
27
26
  false
28
27
  end
29
28
  end