shoulda-matchers 6.2.0 → 6.3.0
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 +4 -4
- data/README.md +0 -1
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +218 -7
- data/lib/shoulda/matchers/active_record/uniqueness/model.rb +13 -1
- data/lib/shoulda/matchers/doublespeak.rb +0 -1
- data/lib/shoulda/matchers/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87a298f618f08949dbe1c165b17dfbfc940a6675b2f790e655c9a43568956c31
|
4
|
+
data.tar.gz: ea5eaad001d24f89a698a4a944f2596da029c019a4bcc2f893c0881146dea058
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcaf6fc8e3e59cf1936c2a346d1a02c1269ab8e231b7820c273873ed81cf6f97501bf15ea44503f357008064f34eaec66bc9a81f2938fd3876078d707979daea
|
7
|
+
data.tar.gz: 94a53d9576ea0df451d2ff0ff34528f8c035699e9d216e877ced2cdff156ae0a5d18bc106dc0b5fc487aebfd56807bd836d2cb9aa51ababfc232be5e3b94c2cf
|
data/README.md
CHANGED
@@ -527,7 +527,6 @@ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
|
527
527
|
|
528
528
|
We love open source software!
|
529
529
|
See [our other projects][community].
|
530
|
-
|
531
530
|
We are [available for hire][hire].
|
532
531
|
|
533
532
|
[community]: https://thoughtbot.com/community?utm_source=github
|
@@ -187,8 +187,95 @@ module Shoulda
|
|
187
187
|
# without_scopes
|
188
188
|
# end
|
189
189
|
#
|
190
|
-
#
|
190
|
+
# ##### with_default
|
191
|
+
#
|
192
|
+
# Use `with_default` to test that the enum is defined with a
|
193
|
+
# default value. A proc can also be passed, and will be called once each
|
194
|
+
# time a new value is needed. (If using Time or Date, it's recommended to
|
195
|
+
# freeze time or date to avoid flaky tests):
|
196
|
+
#
|
197
|
+
# class Issue < ActiveRecord::Base
|
198
|
+
# enum status: [:open, :closed], default: :closed
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# # RSpec
|
202
|
+
# RSpec.describe Issue, type: :model do
|
203
|
+
# it do
|
204
|
+
# should define_enum_for(:status).
|
205
|
+
# with_default(:closed)
|
206
|
+
# end
|
207
|
+
# end
|
208
|
+
#
|
209
|
+
# # Minitest (Shoulda)
|
210
|
+
# class ProcessTest < ActiveSupport::TestCase
|
211
|
+
# should define_enum_for(:status).
|
212
|
+
# with_default(:closed)
|
213
|
+
# end
|
191
214
|
#
|
215
|
+
# ##### validating
|
216
|
+
#
|
217
|
+
# Use `validating` to test that the enum is being validated.
|
218
|
+
# Can take a boolean value and an allowing_nil keyword argument:
|
219
|
+
#
|
220
|
+
# class Issue < ActiveRecord::Base
|
221
|
+
# enum status: [:open, :closed], validate: true
|
222
|
+
# end
|
223
|
+
#
|
224
|
+
# # RSpec
|
225
|
+
# RSpec.describe Issue, type: :model do
|
226
|
+
# it do
|
227
|
+
# should define_enum_for(:status).
|
228
|
+
# validating
|
229
|
+
# end
|
230
|
+
# end
|
231
|
+
#
|
232
|
+
# # Minitest (Shoulda)
|
233
|
+
# class ProcessTest < ActiveSupport::TestCase
|
234
|
+
# should define_enum_for(:status).
|
235
|
+
# validating
|
236
|
+
# end
|
237
|
+
#
|
238
|
+
# class Issue < ActiveRecord::Base
|
239
|
+
# enum status: [:open, :closed], validate: { allow_nil: true }
|
240
|
+
# end
|
241
|
+
#
|
242
|
+
# # RSpec
|
243
|
+
# RSpec.describe Issue, type: :model do
|
244
|
+
# it do
|
245
|
+
# should define_enum_for(:status).
|
246
|
+
# validating(allowing_nil: true)
|
247
|
+
# end
|
248
|
+
# end
|
249
|
+
#
|
250
|
+
# # Minitest (Shoulda)
|
251
|
+
# class ProcessTest < ActiveSupport::TestCase
|
252
|
+
# should define_enum_for(:status).
|
253
|
+
# validating(allowing_nil: true)
|
254
|
+
# end
|
255
|
+
#
|
256
|
+
# ##### without_instance_methods
|
257
|
+
#
|
258
|
+
# Use `without_instance_methods` to exclude the check for instance methods.
|
259
|
+
#
|
260
|
+
# class Issue < ActiveRecord::Base
|
261
|
+
# enum status: [:open, :closed], instance_methods: false
|
262
|
+
# end
|
263
|
+
#
|
264
|
+
# # RSpec
|
265
|
+
# RSpec.describe Issue, type: :model do
|
266
|
+
# it do
|
267
|
+
# should define_enum_for(:status).
|
268
|
+
# without_instance_methods
|
269
|
+
# end
|
270
|
+
# end
|
271
|
+
#
|
272
|
+
# # Minitest (Shoulda)
|
273
|
+
# class ProcessTest < ActiveSupport::TestCase
|
274
|
+
# should define_enum_for(:status).
|
275
|
+
# without_instance_methods
|
276
|
+
# end
|
277
|
+
#
|
278
|
+
# @return [DefineEnumForMatcher]
|
192
279
|
def define_enum_for(attribute_name)
|
193
280
|
DefineEnumForMatcher.new(attribute_name)
|
194
281
|
end
|
@@ -197,7 +284,7 @@ module Shoulda
|
|
197
284
|
class DefineEnumForMatcher
|
198
285
|
def initialize(attribute_name)
|
199
286
|
@attribute_name = attribute_name
|
200
|
-
@options = { expected_enum_values: [], scopes: true }
|
287
|
+
@options = { expected_enum_values: [], scopes: true, instance_methods: true }
|
201
288
|
end
|
202
289
|
|
203
290
|
def description
|
@@ -222,6 +309,12 @@ module Shoulda
|
|
222
309
|
description
|
223
310
|
end
|
224
311
|
|
312
|
+
def validating(value = true, allowing_nil: false)
|
313
|
+
options[:validating] = value
|
314
|
+
options[:allowing_nil] = allowing_nil
|
315
|
+
self
|
316
|
+
end
|
317
|
+
|
225
318
|
def with_values(expected_enum_values)
|
226
319
|
options[:expected_enum_values] = expected_enum_values
|
227
320
|
self
|
@@ -247,6 +340,16 @@ module Shoulda
|
|
247
340
|
self
|
248
341
|
end
|
249
342
|
|
343
|
+
def without_instance_methods
|
344
|
+
options[:instance_methods] = false
|
345
|
+
self
|
346
|
+
end
|
347
|
+
|
348
|
+
def with_default(default_value)
|
349
|
+
options[:default] = default_value
|
350
|
+
self
|
351
|
+
end
|
352
|
+
|
250
353
|
def matches?(subject)
|
251
354
|
@record = subject
|
252
355
|
|
@@ -254,7 +357,9 @@ module Shoulda
|
|
254
357
|
enum_values_match? &&
|
255
358
|
column_type_matches? &&
|
256
359
|
enum_value_methods_exist? &&
|
257
|
-
scope_presence_matches?
|
360
|
+
scope_presence_matches? &&
|
361
|
+
default_value_matches? &&
|
362
|
+
validating_matches?
|
258
363
|
end
|
259
364
|
|
260
365
|
def failure_message
|
@@ -277,6 +382,30 @@ module Shoulda
|
|
277
382
|
|
278
383
|
private
|
279
384
|
|
385
|
+
def validating_matches?
|
386
|
+
return true if options[:validating].nil?
|
387
|
+
|
388
|
+
validator = find_enum_validator
|
389
|
+
|
390
|
+
if expected_validating? == !!validator
|
391
|
+
if validator&.options&.dig(:allow_nil).present? == expected_allowing_nil?
|
392
|
+
true
|
393
|
+
else
|
394
|
+
@failure_message_continuation =
|
395
|
+
"However, #{attribute_name.inspect} is allowing nil values"
|
396
|
+
false
|
397
|
+
end
|
398
|
+
else
|
399
|
+
@failure_message_continuation =
|
400
|
+
if expected_validating?
|
401
|
+
"However, #{attribute_name.inspect} is not being validated"
|
402
|
+
else
|
403
|
+
"However, #{attribute_name.inspect} is being validated"
|
404
|
+
end
|
405
|
+
false
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
280
409
|
attr_reader :attribute_name, :options, :record,
|
281
410
|
:failure_message_continuation
|
282
411
|
|
@@ -292,6 +421,21 @@ module Shoulda
|
|
292
421
|
)
|
293
422
|
end
|
294
423
|
|
424
|
+
if options[:default].present?
|
425
|
+
expectation << ', with a default value of '
|
426
|
+
expectation << Shoulda::Matchers::Util.inspect_value(expected_default_value)
|
427
|
+
end
|
428
|
+
|
429
|
+
if expected_validating?
|
430
|
+
expectation << ', and being validated '
|
431
|
+
expectation <<
|
432
|
+
if expected_allowing_nil?
|
433
|
+
'allowing nil values'
|
434
|
+
else
|
435
|
+
'not allowing nil values'
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
295
439
|
if expected_prefix
|
296
440
|
expectation <<
|
297
441
|
if expected_suffix
|
@@ -413,16 +557,24 @@ module Shoulda
|
|
413
557
|
end
|
414
558
|
|
415
559
|
def enum_value_methods_exist?
|
416
|
-
if
|
417
|
-
true
|
418
|
-
|
560
|
+
if options[:instance_methods]
|
561
|
+
return true if instance_methods_exist?
|
562
|
+
|
419
563
|
message = missing_methods_message
|
564
|
+
message << " (we can't tell which)" if [expected_prefix, expected_suffix].any?
|
565
|
+
|
566
|
+
@failure_message_continuation = message
|
420
567
|
|
421
|
-
|
568
|
+
false
|
569
|
+
elsif instance_methods_exist?
|
570
|
+
message = "#{attribute_name.inspect} does map to these values"
|
571
|
+
message << ' with instance methods, but expected no instance methods'
|
422
572
|
|
423
573
|
@failure_message_continuation = message
|
424
574
|
|
425
575
|
false
|
576
|
+
else
|
577
|
+
true
|
426
578
|
end
|
427
579
|
end
|
428
580
|
|
@@ -471,11 +623,50 @@ module Shoulda
|
|
471
623
|
elsif expected_suffix
|
472
624
|
message << 'configured with either a different suffix or no '
|
473
625
|
message << 'suffix at all'
|
626
|
+
elsif expected_instance_methods?
|
627
|
+
message << 'configured with no instance methods'
|
474
628
|
else
|
475
629
|
''
|
476
630
|
end
|
477
631
|
end
|
478
632
|
|
633
|
+
def default_value_matches?
|
634
|
+
return true if options[:default].blank?
|
635
|
+
|
636
|
+
if actual_default_value.nil?
|
637
|
+
@failure_message_continuation = 'However, no default value was set'
|
638
|
+
return false
|
639
|
+
end
|
640
|
+
|
641
|
+
if actual_default_value == expected_default_value
|
642
|
+
true
|
643
|
+
else
|
644
|
+
String.new.tap do |message|
|
645
|
+
message << 'However, the default value is '
|
646
|
+
message << Shoulda::Matchers::Util.inspect_value(actual_default_value)
|
647
|
+
@failure_message_continuation = message
|
648
|
+
end
|
649
|
+
false
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
def expected_default_value
|
654
|
+
options[:default].respond_to?(:call) ? options[:default].call : options[:default]
|
655
|
+
end
|
656
|
+
|
657
|
+
def actual_default_value
|
658
|
+
attribute_schema = model.attributes_to_define_after_schema_loads[attribute_name.to_s]
|
659
|
+
|
660
|
+
value = case attribute_schema
|
661
|
+
in [_, { default: default_value } ]
|
662
|
+
default_value
|
663
|
+
in [_, default_value]
|
664
|
+
default_value
|
665
|
+
end
|
666
|
+
|
667
|
+
value.respond_to?(:call) ? value.call : value
|
668
|
+
end
|
669
|
+
|
479
670
|
def singleton_methods_exist?
|
480
671
|
expected_singleton_methods.all? do |method|
|
481
672
|
model.singleton_methods.include?(method)
|
@@ -509,6 +700,10 @@ module Shoulda
|
|
509
700
|
end
|
510
701
|
end
|
511
702
|
|
703
|
+
def expected_instance_methods?
|
704
|
+
options[:instance_methods]
|
705
|
+
end
|
706
|
+
|
512
707
|
def expected_prefix
|
513
708
|
if options.include?(:prefix)
|
514
709
|
if options[:prefix] == true
|
@@ -529,6 +724,22 @@ module Shoulda
|
|
529
724
|
end
|
530
725
|
end
|
531
726
|
|
727
|
+
def expected_validating?
|
728
|
+
options[:validating].present?
|
729
|
+
end
|
730
|
+
|
731
|
+
def expected_allowing_nil?
|
732
|
+
options[:allowing_nil].present?
|
733
|
+
end
|
734
|
+
|
735
|
+
def find_enum_validator
|
736
|
+
record.class.validators.detect do |validator|
|
737
|
+
validator.kind == :inclusion &&
|
738
|
+
validator.attributes.include?(attribute_name.to_s) &&
|
739
|
+
validator.options[:in] == expected_enum_values
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
532
743
|
def exclude_scopes?
|
533
744
|
!options[:scopes]
|
534
745
|
end
|
@@ -29,7 +29,19 @@ module Shoulda
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def symlink_to(parent)
|
32
|
-
|
32
|
+
table_name = parent.table_name
|
33
|
+
|
34
|
+
new_class = Class.new(parent) do
|
35
|
+
define_singleton_method :table_name do
|
36
|
+
table_name
|
37
|
+
end
|
38
|
+
|
39
|
+
define_singleton_method :base_class do
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
namespace.set(name, new_class)
|
33
45
|
end
|
34
46
|
|
35
47
|
def to_s
|
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.
|
4
|
+
version: 6.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tammer Saleh
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2024-
|
17
|
+
date: 2024-08-09 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: activesupport
|
@@ -198,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
198
|
- !ruby/object:Gem::Version
|
199
199
|
version: '0'
|
200
200
|
requirements: []
|
201
|
-
rubygems_version: 3.5.
|
201
|
+
rubygems_version: 3.5.3
|
202
202
|
signing_key:
|
203
203
|
specification_version: 4
|
204
204
|
summary: Simple one-liner tests for common Rails functionality
|