shoulda-matchers 6.5.0 → 7.0.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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/lib/shoulda/matchers/action_controller/route_matcher.rb +2 -2
  4. data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
  5. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +4 -4
  6. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +5 -5
  7. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +2 -2
  8. data/lib/shoulda/matchers/active_model/errors.rb +2 -2
  9. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +1 -1
  10. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +1 -1
  11. data/lib/shoulda/matchers/active_model/validation_matcher.rb +5 -4
  12. data/lib/shoulda/matchers/active_model/validator.rb +2 -2
  13. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +137 -4
  14. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +1 -1
  15. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +8 -8
  16. data/lib/shoulda/matchers/doublespeak/double.rb +4 -4
  17. data/lib/shoulda/matchers/doublespeak/method_call.rb +1 -1
  18. data/lib/shoulda/matchers/doublespeak/object_double.rb +3 -3
  19. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +2 -4
  20. data/lib/shoulda/matchers/integrations/configuration.rb +0 -2
  21. data/lib/shoulda/matchers/rails_shim.rb +0 -4
  22. data/lib/shoulda/matchers/routing.rb +1 -1
  23. data/lib/shoulda/matchers/util/word_wrap.rb +4 -4
  24. data/lib/shoulda/matchers/version.rb +1 -1
  25. data/shoulda-matchers.gemspec +3 -2
  26. metadata +20 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28aa81eb37b239f9f7715725027b774736992c82c2f6905b0d244a35f9db080d
4
- data.tar.gz: 2433121dc12d086b12c19f5313abcaf8c885cd03de594dd3bcaae0f9150c4173
3
+ metadata.gz: 63256c77182faa2d6d70c24f7f53d5cbb4c8f723ebea8ab062a912cea898d405
4
+ data.tar.gz: 1bc874eac2eb72cf6e73ff4a8f642deca0f911bb1a8939b7e6d4f257fc1fb3e6
5
5
  SHA512:
6
- metadata.gz: c3dab42effbda8285e424feab81c543bb2e84d9764b513db8007a6b6bb0a2dd923fc76db8f253013dc701588dda5ca314fa3d7e2de9e15af84a8a84f9245670b
7
- data.tar.gz: 6902d75fa7b45c3adc8c97917e9fc1c610be1e99a95bb860ba5112793cdb7653189e4f303f8c879842576a679e3975a520d8ff98dc160ad2168b3fa0b105ecf5
6
+ metadata.gz: 943c4db0909a15216ec5aa90cb01a04400cf000217f59dc70bfbfb9a4ac264466f757963ed66c79e1acc9174b4d42f445d9fac8f590d926a6699592f05108633
7
+ data.tar.gz: 914455300f3ae6ceccfec6ce50cac85f201643e4b1bca4cd152a2c8a6b2c45e161d7ba8b9fb9daf41ce90c9faeaee75bef5f03b985a3d38768cba5a8a040adf9
data/README.md CHANGED
@@ -559,5 +559,4 @@ We are [available for hire][hire].
559
559
  [community]: https://thoughtbot.com/community?utm_source=github
560
560
  [hire]: https://thoughtbot.com/hire-us?utm_source=github
561
561
 
562
-
563
562
  <!-- END /templates/footer.md -->
@@ -125,7 +125,7 @@ module Shoulda
125
125
  # @return [RouteMatcher]
126
126
  #
127
127
  def route(method, path, port: nil)
128
- RouteMatcher.new(self, method, path, port: port)
128
+ RouteMatcher.new(self, method, path, port:)
129
129
  end
130
130
 
131
131
  # @private
@@ -190,7 +190,7 @@ module Shoulda
190
190
  def route_recognized?
191
191
  context.send(
192
192
  :assert_routing,
193
- { method: method, path: path },
193
+ { method:, path: },
194
194
  params,
195
195
  )
196
196
  true
@@ -27,7 +27,7 @@ module Shoulda
27
27
 
28
28
  def extract_params_from_string
29
29
  controller, action = args[0].split('#')
30
- params = (args[1] || {}).merge!(controller: controller, action: action)
30
+ params = (args[1] || {}).merge!(controller:, action:)
31
31
  normalize_values(params)
32
32
  end
33
33
 
@@ -204,9 +204,9 @@ module Shoulda
204
204
  def attribute_changed_value_error
205
205
  AttributeChangedValueError.create(
206
206
  model: object.class,
207
- attribute_name: attribute_name,
208
- value_written: value_written,
209
- value_read: value_read,
207
+ attribute_name:,
208
+ value_written:,
209
+ value_read:,
210
210
  )
211
211
  end
212
212
 
@@ -217,7 +217,7 @@ module Shoulda
217
217
  def attribute_does_not_exist_error
218
218
  AttributeDoesNotExistError.create(
219
219
  model: object.class,
220
- attribute_name: attribute_name,
220
+ attribute_name:,
221
221
  value: value_written,
222
222
  )
223
223
  end
@@ -31,9 +31,9 @@ module Shoulda
31
31
  @_attribute_setter ||= AttributeSetter.new(
32
32
  matcher_name: :allow_value,
33
33
  object: instance,
34
- attribute_name: attribute_name,
35
- value: value,
36
- ignore_interference_by_writer: ignore_interference_by_writer,
34
+ attribute_name:,
35
+ value:,
36
+ ignore_interference_by_writer:,
37
37
  after_set_callback: after_setting_value_callback,
38
38
  )
39
39
  end
@@ -46,9 +46,9 @@ module Shoulda
46
46
  @_validator ||= Validator.new(
47
47
  instance,
48
48
  attribute_to_check_message_against,
49
- context: context,
49
+ context:,
50
50
  expects_strict: expects_strict?,
51
- expected_message: expected_message,
51
+ expected_message:,
52
52
  )
53
53
  end
54
54
 
@@ -672,8 +672,8 @@ pass, or do something else entirely.
672
672
 
673
673
  def default_attribute_message_values
674
674
  defaults = {
675
- model_name: model_name,
676
- instance: instance,
675
+ model_name:,
676
+ instance:,
677
677
  attribute: attribute_to_check_message_against,
678
678
  }
679
679
 
@@ -7,7 +7,7 @@ module Shoulda
7
7
  # @private
8
8
  class NonNullableBooleanError < Shoulda::Matchers::Error
9
9
  def self.create(attribute)
10
- super(attribute: attribute)
10
+ super(attribute:)
11
11
  end
12
12
 
13
13
  attr_accessor :attribute
@@ -24,7 +24,7 @@ Hence, this test will fail and there is no way to make it pass.
24
24
  # @private
25
25
  class CouldNotSetPasswordError < Shoulda::Matchers::Error
26
26
  def self.create(model)
27
- super(model: model)
27
+ super(model:)
28
28
  end
29
29
 
30
30
  attr_accessor :model
@@ -73,7 +73,7 @@ module Shoulda
73
73
 
74
74
  def failure_message_when_negated
75
75
  MESSAGES[:should_not_have_secure_password] %
76
- { subject: @subject.class, description: description }
76
+ { subject: @subject.class, description: }
77
77
  end
78
78
 
79
79
  protected
@@ -153,7 +153,7 @@ module Shoulda
153
153
  matcher.with_message(
154
154
  @expected_message,
155
155
  against: confirmation_attribute,
156
- values: { attribute: attribute },
156
+ values: { attribute: },
157
157
  )
158
158
  end
159
159
  end
@@ -8,6 +8,7 @@ module Shoulda
8
8
  def initialize(attribute)
9
9
  super
10
10
  @attribute = attribute
11
+ @options = {}
11
12
  @expects_strict = false
12
13
  @subject = nil
13
14
  @last_submatcher_run = nil
@@ -106,8 +107,8 @@ module Shoulda
106
107
  def allow_value_matcher(value, message = nil, &block)
107
108
  build_allow_or_disallow_value_matcher(
108
109
  matcher_class: AllowValueMatcher,
109
- value: value,
110
- message: message,
110
+ value:,
111
+ message:,
111
112
  &block
112
113
  )
113
114
  end
@@ -115,8 +116,8 @@ module Shoulda
115
116
  def disallow_value_matcher(value, message = nil, &block)
116
117
  build_allow_or_disallow_value_matcher(
117
118
  matcher_class: DisallowValueMatcher,
118
- value: value,
119
- message: message,
119
+ value:,
120
+ message:,
120
121
  &block
121
122
  )
122
123
  end
@@ -105,8 +105,8 @@ module Shoulda
105
105
  validation_error_messages = record.errors[attribute]
106
106
 
107
107
  {
108
- all_validation_errors: all_validation_errors,
109
- validation_error_messages: validation_error_messages,
108
+ all_validation_errors:,
109
+ validation_error_messages:,
110
110
  validation_exception_message: nil,
111
111
  }
112
112
  rescue ::ActiveModel::StrictValidationFailed => e
@@ -20,6 +20,74 @@ module Shoulda
20
20
  # should have_one_attached(:avatar)
21
21
  # end
22
22
  #
23
+ # #### Qualifiers
24
+ #
25
+ # ##### service
26
+ #
27
+ # Use `service` to assert that the `:service` option was specified.
28
+ #
29
+ # class User < ApplicationRecord
30
+ # has_one_attached :avatar, service: :s3
31
+ # end
32
+ #
33
+ # # RSpec
34
+ # RSpec.describe User, type: :model do
35
+ # it { should have_one_attached(:avatar).service(:s3) }
36
+ # end
37
+ #
38
+ # # Minitest (Shoulda)
39
+ # class UserTest < ActiveSupport::TestCase
40
+ # should have_one_attached(:avatar).service(:s3)
41
+ # end
42
+ #
43
+ # ##### dependent
44
+ #
45
+ # Use `dependent` to assert that the `:dependent` option was specified.
46
+ #
47
+ # class User < ApplicationRecord
48
+ # has_one_attached :avatar, dependent: :destroy
49
+ # end
50
+ #
51
+ # # RSpec
52
+ # RSpec.describe User, type: :model do
53
+ # it { should have_one_attached(:avatar).dependent(:destroy) }
54
+ # end
55
+ #
56
+ # # Minitest (Shoulda)
57
+ # class UserTest < ActiveSupport::TestCase
58
+ # should have_one_attached(:avatar).dependent(:destroy)
59
+ # end
60
+ #
61
+ # ##### strict_loading
62
+ #
63
+ # Use `strict_loading` to assert that the `:strict_loading` option was specified.
64
+ #
65
+ # class User < ApplicationRecord
66
+ # has_one_attached :avatar, strict_loading: true
67
+ # end
68
+ #
69
+ # # RSpec
70
+ # RSpec.describe User, type: :model do
71
+ # it { should have_one_attached(:avatar).strict_loading(true) }
72
+ # end
73
+ #
74
+ # # Minitest (Shoulda)
75
+ # class UserTest < ActiveSupport::TestCase
76
+ # should have_one_attached(:avatar).strict_loading(true)
77
+ # end
78
+ #
79
+ # Default value is true when no argument is specified:
80
+ #
81
+ # # RSpec
82
+ # RSpec.describe User, type: :model do
83
+ # it { should have_one_attached(:avatar).strict_loading }
84
+ # end
85
+ #
86
+ # # Minitest (Shoulda)
87
+ # class UserTest < ActiveSupport::TestCase
88
+ # should have_one_attached(:avatar).strict_loading
89
+ # end
90
+ #
23
91
  # @return [HaveAttachedMatcher]
24
92
  #
25
93
  def have_one_attached(name)
@@ -53,11 +121,12 @@ module Shoulda
53
121
 
54
122
  # @private
55
123
  class HaveAttachedMatcher
56
- attr_reader :name
124
+ attr_reader :name, :options
57
125
 
58
126
  def initialize(macro, name)
59
127
  @macro = macro
60
128
  @name = name
129
+ @options = {}
61
130
  end
62
131
 
63
132
  def description
@@ -78,7 +147,7 @@ Did not expect #{expectation}, but it does.
78
147
  end
79
148
 
80
149
  def expectation
81
- "#{model_class.name} to #{description}"
150
+ "#{model_class.name} to #{description}" + build_expectation_suffix
82
151
  end
83
152
 
84
153
  def matches?(subject)
@@ -87,13 +156,42 @@ Did not expect #{expectation}, but it does.
87
156
  writer_attribute_exists? &&
88
157
  attachments_association_exists? &&
89
158
  blobs_association_exists? &&
90
- eager_loading_scope_exists?
159
+ eager_loading_scope_exists? &&
160
+ service_correct? &&
161
+ dependent_option_correct?
162
+ end
163
+
164
+ OPTION_METHODS = {
165
+ service: -> (value) { value },
166
+ strict_loading: -> (value = true) { value },
167
+ dependent: -> (value) { value },
168
+ }.freeze
169
+
170
+ OPTION_METHODS.each do |option_name, value_processor|
171
+ define_method(option_name) do |*args|
172
+ @options[option_name] = value_processor.call(*args)
173
+ self
174
+ end
91
175
  end
92
176
 
93
177
  private
94
178
 
95
179
  attr_reader :subject, :macro
96
180
 
181
+ def build_expectation_suffix
182
+ String.new.tap do |suffix|
183
+ suffix << " with service :#{options[:service]}" if options.key?(:service)
184
+
185
+ if options.key?(:strict_loading)
186
+ suffix << " with strict_loading option set to #{options[:strict_loading]}"
187
+ end
188
+
189
+ if options.key?(:dependent)
190
+ suffix << " with dependent option set to :#{options[:dependent]}"
191
+ end
192
+ end
193
+ end
194
+
97
195
  def reader_attribute_exists?
98
196
  if subject.respond_to?(name)
99
197
  true
@@ -127,7 +225,7 @@ Did not expect #{expectation}, but it does.
127
225
  :"has_#{macro}",
128
226
  attachments_association_name,
129
227
  ).
130
- conditions(name: name).
228
+ conditions(name:).
131
229
  class_name('ActiveStorage::Attachment').
132
230
  inverse_of(:record)
133
231
  end
@@ -156,6 +254,7 @@ Did not expect #{expectation}, but it does.
156
254
  ).
157
255
  through(attachments_association_name).
158
256
  class_name('ActiveStorage::Blob').
257
+ strict_loading(options[:strict_loading]).
159
258
  source(:blob)
160
259
  end
161
260
 
@@ -179,6 +278,40 @@ Did not expect #{expectation}, but it does.
179
278
  def model_class
180
279
  subject.class
181
280
  end
281
+
282
+ def dependent_option_correct?
283
+ dependent = @options[:dependent]
284
+ return true if dependent.nil? || dependent_option == dependent
285
+
286
+ @failure = 'The dependent option for the association called ' \
287
+ "#{attachments_association_name} is incorrect " \
288
+ "(expected: :#{dependent}, " \
289
+ "actual: :#{dependent_option})"
290
+ false
291
+ end
292
+
293
+ def service_correct?
294
+ service = @options[:service]
295
+ return true if service.nil? || service_name == service
296
+
297
+ @failure = 'The service for the association called ' \
298
+ "#{attachments_association_name} is incorrect " \
299
+ "(expected: :#{service}, " \
300
+ "actual: :#{service_name})"
301
+ false
302
+ end
303
+
304
+ def attachment_reflection
305
+ model_class.attachment_reflections[name.to_s]
306
+ end
307
+
308
+ def service_name
309
+ attachment_reflection.options[:service_name]
310
+ end
311
+
312
+ def dependent_option
313
+ attachment_reflection.options[:dependent]
314
+ end
182
315
  end
183
316
  end
184
317
  end
@@ -71,7 +71,7 @@ module Shoulda
71
71
  def has_expected_action_text?
72
72
  defined?(ActionText::RichText) &&
73
73
  @subject.send(rich_text_attribute).
74
- instance_of?(ActionText::RichText)
74
+ is_a?(ActionText::RichText)
75
75
  end
76
76
 
77
77
  def error_description
@@ -758,9 +758,9 @@ module Shoulda
758
758
  if case_sensitivity_strategy == :sensitive
759
759
  if value == swapcased_value
760
760
  raise NonCaseSwappableValueError.create(
761
- model: model,
761
+ model:,
762
762
  attribute: @attribute,
763
- value: value,
763
+ value:,
764
764
  )
765
765
  end
766
766
 
@@ -785,9 +785,9 @@ module Shoulda
785
785
  else
786
786
  if value == swapcased_value
787
787
  raise NonCaseSwappableValueError.create(
788
- model: model,
788
+ model:,
789
789
  attribute: @attribute,
790
- value: value,
790
+ value:,
791
791
  )
792
792
  end
793
793
 
@@ -966,9 +966,9 @@ module Shoulda
966
966
  new(
967
967
  matcher_name: :validate_uniqueness_of,
968
968
  object: record,
969
- attribute_name: attribute_name,
970
- value: value,
971
- ignore_interference_by_writer: ignore_interference_by_writer,
969
+ attribute_name:,
970
+ value:,
971
+ ignore_interference_by_writer:,
972
972
  )
973
973
  end
974
974
 
@@ -1092,7 +1092,7 @@ different altogether.
1092
1092
  )
1093
1093
  description_for_attribute_setter(
1094
1094
  attribute_setter,
1095
- same_as_existing: same_as_existing,
1095
+ same_as_existing:,
1096
1096
  )
1097
1097
  end
1098
1098
  end
@@ -77,12 +77,12 @@ module Shoulda
77
77
 
78
78
  klass.__send__(:define_method, method_name) do |*args, &block|
79
79
  call = MethodCall.new(
80
- double: double,
80
+ double:,
81
81
  object: self,
82
82
  method_name: _method_name,
83
- args: args,
84
- block: block,
85
- caller: caller,
83
+ args:,
84
+ block:,
85
+ caller:,
86
86
  )
87
87
  implementation.call(call)
88
88
  end
@@ -32,7 +32,7 @@ module Shoulda
32
32
  end
33
33
 
34
34
  def to_hash
35
- { method_name: method_name, args: args }
35
+ { method_name:, args: }
36
36
  end
37
37
 
38
38
  def inspect
@@ -24,9 +24,9 @@ module Shoulda
24
24
 
25
25
  def method_missing(method_name, *args, &block)
26
26
  call = MethodCall.new(
27
- method_name: method_name,
28
- args: args,
29
- block: block,
27
+ method_name:,
28
+ args:,
29
+ block:,
30
30
  caller: ::Kernel.caller,
31
31
  )
32
32
  calls << call
@@ -446,8 +446,7 @@ module Shoulda
446
446
  rescue Module::DelegationError
447
447
  false
448
448
  rescue NoMethodError => e
449
- if e.message =~
450
- /undefined method `#{delegate_method}' for nil/
449
+ if e.message =~ /undefined method [`']#{delegate_method}[`'] for nil/
451
450
  false
452
451
  else
453
452
  raise e
@@ -467,8 +466,7 @@ module Shoulda
467
466
  rescue Module::DelegationError
468
467
  false
469
468
  rescue NoMethodError => e
470
- if e.message =~
471
- /private method `#{delegating_method}' called for/
469
+ if e.message =~ /private method [`']#{delegating_method}[`'] called for/
472
470
  true
473
471
  else
474
472
  raise e
@@ -1,5 +1,3 @@
1
- require 'set'
2
-
3
1
  module Shoulda
4
2
  module Matchers
5
3
  module Integrations
@@ -21,10 +21,6 @@ module Shoulda
21
21
  Gem::Version.new('0')
22
22
  end
23
23
 
24
- def active_model_st_6_1?
25
- Gem::Requirement.new('< 6.1').satisfied_by?(active_model_version)
26
- end
27
-
28
24
  def active_model_lt_7?
29
25
  Gem::Requirement.new('< 7').satisfied_by?(active_model_version)
30
26
  end
@@ -3,7 +3,7 @@ module Shoulda
3
3
  # @private
4
4
  module Routing
5
5
  def route(method, path, port: nil)
6
- ActionController::RouteMatcher.new(self, method, path, port: port)
6
+ ActionController::RouteMatcher.new(self, method, path, port:)
7
7
  end
8
8
  end
9
9
  end
@@ -34,7 +34,7 @@ module Shoulda
34
34
 
35
35
  def wrapped_paragraphs
36
36
  paragraphs.map do |paragraph|
37
- Paragraph.new(paragraph, indent: indent).wrap
37
+ Paragraph.new(paragraph, indent:).wrap
38
38
  end
39
39
  end
40
40
  end
@@ -100,11 +100,11 @@ module Shoulda
100
100
  end
101
101
 
102
102
  def wrap_lines(lines)
103
- lines.map { |line| Line.new(line, indent: indent).wrap }
103
+ lines.map { |line| Line.new(line, indent:).wrap }
104
104
  end
105
105
 
106
106
  def wrap_generic_paragraph
107
- Line.new(combine_paragraph_into_one_line, indent: indent).wrap
107
+ Line.new(combine_paragraph_into_one_line, indent:).wrap
108
108
  end
109
109
 
110
110
  def combine_paragraph_into_one_line
@@ -188,7 +188,7 @@ module Shoulda
188
188
  leftover = line[index + 1..]
189
189
  end
190
190
 
191
- { fitted_line: fitted_line, leftover: leftover }
191
+ { fitted_line:, leftover: }
192
192
  end
193
193
 
194
194
  def determine_where_to_break_line(line, args)
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '6.5.0'.freeze
4
+ VERSION = '7.0.1'.freeze
5
5
  end
6
6
  end
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
36
36
  'shoulda-matchers.gemspec']
37
37
  s.require_paths = ['lib']
38
38
 
39
- s.required_ruby_version = '>= 3.0.5'
40
- s.add_dependency('activesupport', '>= 5.2.0')
39
+ s.required_ruby_version = '>= 3.2'
40
+ s.add_dependency 'activesupport', '>= 7.1'
41
+ s.add_development_dependency 'mutex_m'
41
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoulda-matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.0
4
+ version: 7.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tammer Saleh
@@ -11,10 +11,9 @@ authors:
11
11
  - Matt Jankowski
12
12
  - Stafford Brunk
13
13
  - Elliot Winkler
14
- autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
- date: 2025-04-25 00:00:00.000000000 Z
16
+ date: 2025-10-31 00:00:00.000000000 Z
18
17
  dependencies:
19
18
  - !ruby/object:Gem::Dependency
20
19
  name: activesupport
@@ -22,14 +21,28 @@ dependencies:
22
21
  requirements:
23
22
  - - ">="
24
23
  - !ruby/object:Gem::Version
25
- version: 5.2.0
24
+ version: '7.1'
26
25
  type: :runtime
27
26
  prerelease: false
28
27
  version_requirements: !ruby/object:Gem::Requirement
29
28
  requirements:
30
29
  - - ">="
31
30
  - !ruby/object:Gem::Version
32
- version: 5.2.0
31
+ version: '7.1'
32
+ - !ruby/object:Gem::Dependency
33
+ name: mutex_m
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
33
46
  description: 'Shoulda Matchers provides RSpec- and Minitest-compatible one-liners
34
47
  to test common Rails functionality that, if written by hand, would be much longer,
35
48
  more complex, and error-prone. '
@@ -183,7 +196,6 @@ metadata:
183
196
  documentation_uri: https://matchers.shoulda.io/docs
184
197
  homepage_uri: https://matchers.shoulda.io
185
198
  source_code_uri: https://github.com/thoughtbot/shoulda-matchers
186
- post_install_message:
187
199
  rdoc_options: []
188
200
  require_paths:
189
201
  - lib
@@ -191,15 +203,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
203
  requirements:
192
204
  - - ">="
193
205
  - !ruby/object:Gem::Version
194
- version: 3.0.5
206
+ version: '3.2'
195
207
  required_rubygems_version: !ruby/object:Gem::Requirement
196
208
  requirements:
197
209
  - - ">="
198
210
  - !ruby/object:Gem::Version
199
211
  version: '0'
200
212
  requirements: []
201
- rubygems_version: 3.5.3
202
- signing_key:
213
+ rubygems_version: 3.6.9
203
214
  specification_version: 4
204
215
  summary: Simple one-liner tests for common Rails functionality
205
216
  test_files: []