rspec-mocks 3.11.0 → 3.12.1

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: 12ce7d4b5f6accc3fb2b6af82646843de8ffd500352d4ca5367985e28fec0805
4
- data.tar.gz: 9643bc17b54bd21725aa39946eacda8207e327bdb592a9e0be821ee42c59bddb
3
+ metadata.gz: 26d2a0b4b29906b9299801a379eafbad373822822ad30b769ef2bef2e9a4b22b
4
+ data.tar.gz: b2196b0f0111c48cb88398bb1071c9047fa637853da0ac684fc3d57d5ec7fc71
5
5
  SHA512:
6
- metadata.gz: 1a1fc3ad0ca28d5371d74985f236f9c222fc310743062a5e8746c5f995803bfd5b63de26b673b94460c6ec47eedfbb150425fe3bb59f0e5bdaf4d639ffe0bc0d
7
- data.tar.gz: 352761f69232f8b5afb6ac918bb596c5961017f622f2aec36052f5f69c426449a51ef2af26394951cad5c7706a165446a9d80d6e01adafeb87e4f6e0804a46af
6
+ metadata.gz: c96f4c1dc4c9f99e0d222c2aeb054d5aa6d18a7b18e58df7a2235644c3d91745590346cb74ef8102420e658d748ded36ce1c90727bac6158770e3625f4817aed
7
+ data.tar.gz: 7539266eec67cb3e522855f9a446b9e8a90aef2947d19ce01c69c4e2c6be033cf0e0c01f8b115d0d2f08fc7391e81e355514aeaaa3dc1364bff147bf489e1d19
checksums.yaml.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,5 +1,48 @@
1
1
  ### Development
2
- [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.0...3-11-maintenance)
2
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.1...3-12-maintenance)
3
+
4
+ ### 3.12.1 / 2022-12-10
5
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.0...v3.12.1)
6
+
7
+ Bug Fixes:
8
+
9
+ * Remove empty diff marker when a diff only contains console codes. (Jon Rowe, #1506)
10
+ * Show keyword vs hash diff marker when arguments are not `==` (Jon Rowe, #1506)
11
+ * Change check to detect frozen objects to rescue errors rather than
12
+ pre-empting by checking `frozen?` due to some objects mis-behaving.
13
+ (Keegan Roth, #1401)
14
+ * Prevent unfulfilled expectations using `expect_any_instance_of` across a class
15
+ inheritance boundary from raising rather than failing. (Jon Rowe, #1496)
16
+ * Prevent a misleading error message when using `allow(...).not_to` with
17
+ unsupported matchers. (Phil Pirozhkov, #1503)
18
+
19
+ ### 3.12.0 / 2022-10-26
20
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.2...v3.12.0)
21
+
22
+ Enhancements:
23
+
24
+ * Improve diff output when diffing keyword arguments against hashes.
25
+ (Jean Boussier, #1461)
26
+
27
+ ### 3.11.2 / 2022-10-25
28
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.1...v3.11.2)
29
+
30
+ Bug Fixes:
31
+
32
+ * Use the original implementation of `Class.new` to detect overridden definitions
33
+ of `new` rather than the owner, fixing detection of "double aliased" methods
34
+ in Ruby 3 and above. (Benoit Daloze, #1470, #1476)
35
+ * Support keyword argument semantics when constraining argument expectations using
36
+ `with` on Ruby 3.0+ with `instance_double` (Andrii Malyshko, #1473)
37
+
38
+ ### 3.11.1 / 2022-03-31
39
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.0...v3.11.1)
40
+
41
+ Bug Fixes:
42
+
43
+ * Add extra `ruby2_keywords` calls to properly designate methods using
44
+ `*args` to pass keyword around, fixes an issue with TruffleRuby.
45
+ (Benoit Daloze, #1464)
3
46
 
4
47
  ### 3.11.0 / 2022-02-09
5
48
  [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.3...v3.11.0)
@@ -49,7 +49,7 @@ module RSpec
49
49
  # @private
50
50
  def unfulfilled_expectations
51
51
  @chains_by_method_name.map do |method_name, chains|
52
- method_name.to_s if ExpectationChain === chains.last unless chains.last.expectation_fulfilled?
52
+ method_name.to_s if ExpectationChain === chains.last && !chains.last.expectation_fulfilled?
53
53
  end.compact
54
54
  end
55
55
 
@@ -46,7 +46,7 @@ module RSpec
46
46
  @expected_args = expected_args
47
47
  ensure_expected_args_valid!
48
48
  end
49
- ruby2_keywords :initialize if Module.private_method_defined?(:ruby2_keywords)
49
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
50
50
 
51
51
  # @api public
52
52
  # @param [Array] actual_args
@@ -71,6 +71,7 @@ module RSpec
71
71
 
72
72
  Support::FuzzyMatcher.values_match?(expected_args, actual_args)
73
73
  end
74
+ ruby2_keywords :args_match? if respond_to?(:ruby2_keywords, true)
74
75
 
75
76
  # @private
76
77
  # Resolves abstract arg placeholders like `no_args` and `any_args` into
@@ -268,11 +268,32 @@ module RSpec
268
268
  def error_message(expectation, args_for_multiple_calls)
269
269
  expected_args = format_args(expectation.expected_args)
270
270
  actual_args = format_received_args(args_for_multiple_calls)
271
+
272
+ if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash?
273
+ expected_hash = expectation.expected_args.last
274
+ actual_hash = args_for_multiple_calls.last.last
275
+ if Hash === expected_hash && Hash === actual_hash &&
276
+ (Hash.ruby2_keywords_hash?(expected_hash) != Hash.ruby2_keywords_hash?(actual_hash))
277
+
278
+ actual_description = Hash.ruby2_keywords_hash?(actual_hash) ? " (keyword arguments)" : " (options hash)"
279
+ expected_description = Hash.ruby2_keywords_hash?(expected_hash) ? " (keyword arguments)" : " (options hash)"
280
+
281
+ if actual_description != expected_description
282
+ actual_args += actual_description
283
+ expected_args += expected_description
284
+ end
285
+ end
286
+ end
287
+
271
288
  message = default_error_message(expectation, expected_args, actual_args)
272
289
 
273
290
  if args_for_multiple_calls.one?
274
291
  diff = diff_message(expectation.expected_args, args_for_multiple_calls.first)
275
- message << "\nDiff:#{diff}" unless diff.strip.empty?
292
+ if RSpec::Mocks.configuration.color?
293
+ message << "\nDiff:#{diff}" unless diff.gsub(/\e\[\d+m/, '').strip.empty?
294
+ else
295
+ message << "\nDiff:#{diff}" unless diff.strip.empty?
296
+ end
276
297
  end
277
298
 
278
299
  message
@@ -16,7 +16,7 @@ module RSpec
16
16
  @subject = nil
17
17
  end
18
18
 
19
- def name
19
+ def matcher_name
20
20
  "have_received"
21
21
  end
22
22
 
@@ -13,7 +13,7 @@ module RSpec
13
13
  @recorded_customizations = []
14
14
  end
15
15
 
16
- def name
16
+ def matcher_name
17
17
  "receive"
18
18
  end
19
19
 
@@ -62,7 +62,7 @@ module RSpec
62
62
  @recorded_customizations << ExpectationCustomization.new(method, args, block)
63
63
  self
64
64
  end
65
- ruby2_keywords(method) if Module.private_method_defined?(:ruby2_keywords)
65
+ ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
66
66
  end
67
67
 
68
68
  private
@@ -20,7 +20,7 @@ module RSpec
20
20
  end
21
21
  end
22
22
 
23
- def name
23
+ def matcher_name
24
24
  "receive_message_chain"
25
25
  end
26
26
 
@@ -10,7 +10,7 @@ module RSpec
10
10
  @backtrace_line = CallerFilter.first_non_rspec_line
11
11
  end
12
12
 
13
- def name
13
+ def matcher_name
14
14
  "receive_messages"
15
15
  end
16
16
 
@@ -139,9 +139,12 @@ module RSpec
139
139
  # counter.increment
140
140
  # expect(counter.count).to eq(original_count + 1)
141
141
  def and_call_original
142
- wrap_original(__method__) do |original, *args, &block|
143
- original.call(*args, &block)
142
+ block = lambda do |original, *args, &b|
143
+ original.call(*args, &b)
144
144
  end
145
+ block = block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
146
+
147
+ wrap_original(__method__, &block)
145
148
  end
146
149
 
147
150
  # Decorates the stubbed method with the supplied block. The original
@@ -364,7 +367,7 @@ module RSpec
364
367
  @argument_list_matcher = ArgumentListMatcher.new(*args)
365
368
  self
366
369
  end
367
- ruby2_keywords(:with) if Module.private_method_defined?(:ruby2_keywords)
370
+ ruby2_keywords(:with) if respond_to?(:ruby2_keywords, true)
368
371
 
369
372
  # Expect messages to be received in a specific order.
370
373
  #
@@ -403,7 +406,6 @@ module RSpec
403
406
  # some collaborators it delegates to for this stuff but for now this was
404
407
  # the simplest way to split the public from private stuff to make it
405
408
  # easier to publish the docs for the APIs we want published.
406
- # rubocop:disable Metrics/ModuleLength
407
409
  module ImplementationDetails
408
410
  attr_accessor :error_generator, :implementation
409
411
  attr_reader :message
@@ -461,18 +463,22 @@ module RSpec
461
463
  def matches?(message, *args)
462
464
  @message == message && @argument_list_matcher.args_match?(*args)
463
465
  end
466
+ ruby2_keywords :matches? if respond_to?(:ruby2_keywords, true)
464
467
 
465
468
  def safe_invoke(parent_stub, *args, &block)
466
469
  invoke_incrementing_actual_calls_by(1, false, parent_stub, *args, &block)
467
470
  end
471
+ ruby2_keywords :safe_invoke if respond_to?(:ruby2_keywords, true)
468
472
 
469
473
  def invoke(parent_stub, *args, &block)
470
474
  invoke_incrementing_actual_calls_by(1, true, parent_stub, *args, &block)
471
475
  end
476
+ ruby2_keywords :invoke if respond_to?(:ruby2_keywords, true)
472
477
 
473
478
  def invoke_without_incrementing_received_count(parent_stub, *args, &block)
474
479
  invoke_incrementing_actual_calls_by(0, true, parent_stub, *args, &block)
475
480
  end
481
+ ruby2_keywords :invoke_without_incrementing_received_count if respond_to?(:ruby2_keywords, true)
476
482
 
477
483
  def negative?
478
484
  @expected_received_count == 0 && !@at_least
@@ -621,6 +627,7 @@ module RSpec
621
627
  @actual_received_count += increment
622
628
  end
623
629
  end
630
+ ruby2_keywords :invoke_incrementing_actual_calls_by if respond_to?(:ruby2_keywords, true)
624
631
 
625
632
  def has_been_invoked?
626
633
  @actual_received_count > 0
@@ -678,7 +685,6 @@ module RSpec
678
685
  nil
679
686
  end
680
687
  end
681
- # rubocop:enable Metrics/ModuleLength
682
688
 
683
689
  include ImplementationDetails
684
690
  end
@@ -755,6 +761,7 @@ module RSpec
755
761
  action.call(*args, &block)
756
762
  end.last
757
763
  end
764
+ ruby2_keywords :call if respond_to?(:ruby2_keywords, true)
758
765
 
759
766
  def present?
760
767
  actions.any?
@@ -800,6 +807,7 @@ module RSpec
800
807
  def call(*args, &block)
801
808
  @block.call(@method, *args, &block)
802
809
  end
810
+ ruby2_keywords :call if respond_to?(:ruby2_keywords, true)
803
811
 
804
812
  private
805
813
 
@@ -2,6 +2,9 @@ module RSpec
2
2
  module Mocks
3
3
  # @private
4
4
  class MethodDouble
5
+ # @private TODO: drop in favor of FrozenError in ruby 2.5+
6
+ FROZEN_ERROR_MSG = /can't modify frozen/
7
+
5
8
  # @private
6
9
  attr_reader :method_name, :object, :expectations, :stubs, :method_stasher
7
10
 
@@ -63,11 +66,21 @@ module RSpec
63
66
  define_method(method_name) do |*args, &block|
64
67
  method_double.proxy_method_invoked(self, *args, &block)
65
68
  end
69
+ # This can't be `if respond_to?(:ruby2_keywords, true)`,
70
+ # see https://github.com/rspec/rspec-mocks/pull/1385#issuecomment-755340298
66
71
  ruby2_keywords(method_name) if Module.private_method_defined?(:ruby2_keywords)
67
72
  __send__(visibility, method_name)
68
73
  end
69
74
 
70
75
  @method_is_proxied = true
76
+ rescue RuntimeError, TypeError => e
77
+ # TODO: drop in favor of FrozenError in ruby 2.5+
78
+ # RuntimeError (and FrozenError) for ruby 2.x
79
+ # TypeError for ruby 1.x
80
+ if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
81
+ raise ArgumentError, "Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations."
82
+ end
83
+ raise
71
84
  end
72
85
 
73
86
  # The implementation of the proxied method. Subclasses may override this
@@ -77,10 +90,10 @@ module RSpec
77
90
  def proxy_method_invoked(_obj, *args, &block)
78
91
  @proxy.message_received method_name, *args, &block
79
92
  end
93
+ ruby2_keywords :proxy_method_invoked if respond_to?(:ruby2_keywords, true)
80
94
 
81
95
  # @private
82
96
  def restore_original_method
83
- return show_frozen_warning if object_singleton_class.frozen?
84
97
  return unless @method_is_proxied
85
98
 
86
99
  remove_method_from_definition_target
@@ -88,6 +101,14 @@ module RSpec
88
101
  restore_original_visibility
89
102
 
90
103
  @method_is_proxied = false
104
+ rescue RuntimeError, TypeError => e
105
+ # TODO: drop in favor of FrozenError in ruby 2.5+
106
+ # RuntimeError (and FrozenError) for ruby 2.x
107
+ # TypeError for ruby 1.x
108
+ if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
109
+ return show_frozen_warning
110
+ end
111
+ raise
91
112
  end
92
113
 
93
114
  # @private
@@ -185,11 +185,23 @@ module RSpec
185
185
  def self.applies_to?(method_name)
186
186
  return false unless method_name == :new
187
187
  klass = yield
188
- return false unless klass.respond_to?(:new, true)
188
+ return false unless ::Class === klass && klass.respond_to?(:new, true)
189
189
 
190
190
  # We only want to apply our special logic to normal `new` methods.
191
191
  # Methods that the user has monkeyed with should be left as-is.
192
- ::RSpec::Support.method_handle_for(klass, :new).owner == ::Class
192
+ uses_class_new?(klass)
193
+ end
194
+
195
+ if RUBY_VERSION.to_i >= 3
196
+ CLASS_NEW = ::Class.instance_method(:new)
197
+
198
+ def self.uses_class_new?(klass)
199
+ ::RSpec::Support.method_handle_for(klass, :new) == CLASS_NEW.bind(klass)
200
+ end
201
+ else # Ruby 2's Method#== is too strict
202
+ def self.uses_class_new?(klass)
203
+ ::RSpec::Support.method_handle_for(klass, :new).owner == ::Class
204
+ end
193
205
  end
194
206
 
195
207
  def with_signature
@@ -35,15 +35,9 @@ module RSpec
35
35
 
36
36
  # @private
37
37
  def ensure_can_be_proxied!(object)
38
- return unless object.is_a?(Symbol) || object.frozen?
39
- return if object.nil?
38
+ return unless object.is_a?(Symbol)
40
39
 
41
- msg = "Cannot proxy frozen objects"
42
- if Symbol === object
43
- msg << ". Symbols such as #{object} cannot be mocked or stubbed."
44
- else
45
- msg << ", rspec-mocks relies on proxies for method stubbing and expectations."
46
- end
40
+ msg = "Cannot proxy frozen objects. Symbols such as #{object} cannot be mocked or stubbed."
47
41
  raise ArgumentError, msg
48
42
  end
49
43
 
@@ -230,6 +224,7 @@ module RSpec
230
224
  @object.__send__(:method_missing, message, *args, &block)
231
225
  end
232
226
  end
227
+ ruby2_keywords :message_received if respond_to?(:ruby2_keywords, true)
233
228
 
234
229
  # @private
235
230
  def raise_unexpected_message_error(method_name, args)
@@ -279,12 +274,14 @@ module RSpec
279
274
  expectation.matches?(method_name, *args)
280
275
  end
281
276
  end
277
+ ruby2_keywords :find_matching_expectation if respond_to?(:ruby2_keywords, true)
282
278
 
283
279
  def find_almost_matching_expectation(method_name, *args)
284
280
  find_best_matching_expectation_for(method_name) do |expectation|
285
281
  expectation.matches_name_but_not_args(method_name, *args)
286
282
  end
287
283
  end
284
+ ruby2_keywords :find_almost_matching_expectation if respond_to?(:ruby2_keywords, true)
288
285
 
289
286
  def find_best_matching_expectation_for(method_name)
290
287
  first_match = nil
@@ -301,10 +298,12 @@ module RSpec
301
298
  def find_matching_method_stub(method_name, *args)
302
299
  method_double_for(method_name).stubs.find { |stub| stub.matches?(method_name, *args) }
303
300
  end
301
+ ruby2_keywords :find_matching_method_stub if respond_to?(:ruby2_keywords, true)
304
302
 
305
303
  def find_almost_matching_stub(method_name, *args)
306
304
  method_double_for(method_name).stubs.find { |stub| stub.matches_name_but_not_args(method_name, *args) }
307
305
  end
306
+ ruby2_keywords :find_almost_matching_stub if respond_to?(:ruby2_keywords, true)
308
307
  end
309
308
 
310
309
  # @private
@@ -360,6 +359,7 @@ module RSpec
360
359
  end
361
360
  super
362
361
  end
362
+ ruby2_keywords :message_received if respond_to?(:ruby2_keywords, true)
363
363
 
364
364
  private
365
365
 
@@ -54,7 +54,7 @@ module RSpec
54
54
 
55
55
  def raise_negation_unsupported(method_name, matcher)
56
56
  raise NegationUnsupportedError,
57
- "`#{expression}(...).#{method_name} #{matcher.name}` is not supported since it " \
57
+ "`#{expression}(...).#{method_name} #{matcher.matcher_name}` is not supported since it " \
58
58
  "doesn't really make sense. What would it even mean?"
59
59
  end
60
60
  end
@@ -31,6 +31,7 @@ module RSpec
31
31
  end
32
32
  end
33
33
  end
34
+ ruby2_keywords(:with) if respond_to?(:ruby2_keywords, true)
34
35
 
35
36
  private
36
37
 
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec mocks.
4
4
  module Version
5
5
  # Version of RSpec mocks currently in use in SemVer format.
6
- STRING = '3.11.0'
6
+ STRING = '3.12.1'
7
7
  end
8
8
  end
9
9
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-mocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.11.0
4
+ version: 3.12.1
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: 2022-12-10 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.12.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.12.0
64
64
  - !ruby/object:Gem::Dependency
65
65
  name: diff-lcs
66
66
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +194,7 @@ licenses:
194
194
  - MIT
195
195
  metadata:
196
196
  bug_tracker_uri: https://github.com/rspec/rspec-mocks/issues
197
- changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.11.0/Changelog.md
197
+ changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.12.1/Changelog.md
198
198
  documentation_uri: https://rspec.info/documentation/
199
199
  mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
200
200
  source_code_uri: https://github.com/rspec/rspec-mocks
@@ -214,8 +214,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
214
  - !ruby/object:Gem::Version
215
215
  version: '0'
216
216
  requirements: []
217
- rubygems_version: 3.3.3
217
+ rubygems_version: 3.3.26
218
218
  signing_key:
219
219
  specification_version: 4
220
- summary: rspec-mocks-3.11.0
220
+ summary: rspec-mocks-3.12.1
221
221
  test_files: []
metadata.gz.sig CHANGED
Binary file