shoulda-matchers 5.3.0 → 6.1.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +26 -9
  4. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +7 -9
  5. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +13 -15
  6. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +10 -1
  7. data/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
  8. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +7 -0
  9. data/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +1 -1
  10. data/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +16 -6
  11. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +0 -6
  12. data/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +532 -0
  13. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +3 -3
  14. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +4 -3
  15. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +64 -9
  16. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +40 -96
  17. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +6 -7
  18. data/lib/shoulda/matchers/active_model/validation_matcher.rb +6 -0
  19. data/lib/shoulda/matchers/active_model/validator.rb +4 -0
  20. data/lib/shoulda/matchers/active_model.rb +2 -1
  21. data/lib/shoulda/matchers/active_record/association_matcher.rb +31 -11
  22. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +23 -19
  23. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +27 -23
  24. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +0 -8
  25. data/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
  26. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +46 -6
  27. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +24 -13
  28. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +3 -5
  29. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +1 -1
  30. data/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
  31. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +82 -70
  32. data/lib/shoulda/matchers/active_record.rb +2 -0
  33. data/lib/shoulda/matchers/doublespeak/double_collection.rb +2 -6
  34. data/lib/shoulda/matchers/doublespeak/world.rb +2 -6
  35. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +13 -15
  36. data/lib/shoulda/matchers/rails_shim.rb +8 -6
  37. data/lib/shoulda/matchers/util/word_wrap.rb +1 -1
  38. data/lib/shoulda/matchers/util.rb +17 -19
  39. data/lib/shoulda/matchers/version.rb +1 -1
  40. data/lib/shoulda/matchers.rb +2 -2
  41. data/shoulda-matchers.gemspec +1 -1
  42. metadata +11 -8
  43. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +0 -136
@@ -411,9 +411,29 @@ module Shoulda
411
411
  if scopes_match?
412
412
  true
413
413
  else
414
- @failure_reason = 'Expected the validation '
414
+ @failure_reason = String.new('Expected the validation ').tap do |failure_reason_string|
415
+ failure_reason_string <<
416
+ if expected_scopes.empty?
417
+ 'not to be scoped to anything, '
418
+ else
419
+ "to be scoped to #{inspected_expected_scopes}, "
420
+ end
421
+
422
+ if actual_sets_of_scopes.any?
423
+ failure_reason_string << 'but it was scoped to '
424
+ failure_reason_string << "#{inspected_actual_scopes} instead."
425
+ else
426
+ failure_reason_string << 'but it was not scoped to anything.'
427
+ end
428
+ end
415
429
 
416
- @failure_reason <<
430
+ false
431
+ end
432
+ end
433
+
434
+ def build_failure_reason
435
+ String.new('Expected the validation ').tap do |failure_reason_string|
436
+ failure_reason_string <<
417
437
  if expected_scopes.empty?
418
438
  'not to be scoped to anything, '
419
439
  else
@@ -421,27 +441,25 @@ module Shoulda
421
441
  end
422
442
 
423
443
  if actual_sets_of_scopes.any?
424
- @failure_reason << 'but it was scoped to '
425
- @failure_reason << "#{inspected_actual_scopes} instead."
444
+ failure_reason_string << 'but it was scoped to '
445
+ failure_reason_string << "#{inspected_actual_scopes} instead."
426
446
  else
427
- @failure_reason << 'but it was not scoped to anything.'
447
+ failure_reason_string << 'but it was not scoped to anything.'
428
448
  end
429
-
430
- false
431
449
  end
432
450
  end
433
451
 
434
452
  def does_not_match_scopes_configuration?
435
453
  if scopes_match?
436
- @failure_reason = 'Expected the validation '
437
-
438
- if expected_scopes.empty?
439
- @failure_reason << 'to be scoped to nothing, '
440
- @failure_reason << 'but it was scoped to '
441
- @failure_reason << "#{inspected_actual_scopes} instead."
442
- else
443
- @failure_reason << 'not to be scoped to '
444
- @failure_reason << inspected_expected_scopes
454
+ @failure_reason = String.new('Expected the validation ').tap do |failure_reason|
455
+ if expected_scopes.empty?
456
+ failure_reason << 'to be scoped to nothing, '
457
+ failure_reason << 'but it was scoped to '
458
+ failure_reason << "#{inspected_actual_scopes} instead."
459
+ else
460
+ failure_reason << 'not to be scoped to '
461
+ failure_reason << inspected_expected_scopes
462
+ end
445
463
  end
446
464
 
447
465
  false
@@ -618,20 +636,18 @@ module Shoulda
618
636
  else
619
637
  inspected_scopes = scopes_missing_on_model.map(&:inspect)
620
638
 
621
- reason = ''
622
-
623
- reason << inspected_scopes.to_sentence
624
-
625
- reason <<
626
- if inspected_scopes.many?
627
- ' do not seem to be attributes'
628
- else
629
- ' does not seem to be an attribute'
630
- end
639
+ @failure_reason = String.new.tap do |reason|
640
+ reason << inspected_scopes.to_sentence
631
641
 
632
- reason << " on #{model.name}."
642
+ reason <<
643
+ if inspected_scopes.many?
644
+ ' do not seem to be attributes'
645
+ else
646
+ ' does not seem to be an attribute'
647
+ end
633
648
 
634
- @failure_reason = reason
649
+ reason << " on #{model.name}."
650
+ end
635
651
 
636
652
  false
637
653
  end
@@ -643,20 +659,18 @@ module Shoulda
643
659
  else
644
660
  inspected_scopes = scopes_present_on_model.map(&:inspect)
645
661
 
646
- reason = ''
647
-
648
- reason << inspected_scopes.to_sentence
649
-
650
- reason <<
651
- if inspected_scopes.many?
652
- ' seem to be attributes'
653
- else
654
- ' seems to be an attribute'
655
- end
662
+ @failure_reason = String.new.tap do |reason|
663
+ reason << inspected_scopes.to_sentence
656
664
 
657
- reason << " on #{model.name}."
665
+ reason <<
666
+ if inspected_scopes.many?
667
+ ' seem to be attributes'
668
+ else
669
+ ' seems to be an attribute'
670
+ end
658
671
 
659
- @failure_reason = reason
672
+ reason << " on #{model.name}."
673
+ end
660
674
 
661
675
  false
662
676
  end
@@ -936,45 +950,43 @@ module Shoulda
936
950
  end
937
951
 
938
952
  def failure_message_preface # rubocop:disable Metrics/MethodLength
939
- prefix = ''
940
-
941
- if @existing_record_created
942
- prefix << "After taking the given #{model.name}"
953
+ String.new.tap do |prefix|
954
+ if @existing_record_created
955
+ prefix << "After taking the given #{model.name}"
956
+
957
+ if attribute_setter_for_existing_record
958
+ prefix << ', setting '
959
+ prefix << description_for_attribute_setter(
960
+ attribute_setter_for_existing_record,
961
+ )
962
+ else
963
+ prefix << ", whose :#{attribute} is "
964
+ prefix << "‹#{existing_value_read.inspect}›"
965
+ end
943
966
 
944
- if attribute_setter_for_existing_record
945
- prefix << ', setting '
967
+ prefix << ', and saving it as the existing record, then'
968
+ elsif attribute_setter_for_existing_record
969
+ prefix << "Given an existing #{model.name},"
970
+ prefix << ' after setting '
946
971
  prefix << description_for_attribute_setter(
947
972
  attribute_setter_for_existing_record,
948
973
  )
974
+ prefix << ', then'
949
975
  else
950
- prefix << ", whose :#{attribute} is "
951
- prefix << "‹#{existing_value_read.inspect}›"
976
+ prefix << "Given an existing #{model.name} whose :#{attribute}"
977
+ prefix << ' is '
978
+ prefix << Shoulda::Matchers::Util.inspect_value(
979
+ existing_value_read,
980
+ )
981
+ prefix << ', after'
952
982
  end
953
983
 
954
- prefix << ', and saving it as the existing record, then'
955
- elsif attribute_setter_for_existing_record
956
- prefix << "Given an existing #{model.name},"
957
- prefix << ' after setting '
958
- prefix << description_for_attribute_setter(
959
- attribute_setter_for_existing_record,
960
- )
961
- prefix << ', then'
962
- else
963
- prefix << "Given an existing #{model.name} whose :#{attribute}"
964
- prefix << ' is '
965
- prefix << Shoulda::Matchers::Util.inspect_value(
966
- existing_value_read,
967
- )
968
- prefix << ', after'
969
- end
970
-
971
- prefix << " making a new #{model.name} and setting "
984
+ prefix << " making a new #{model.name} and setting "
972
985
 
973
- prefix << descriptions_for_attribute_setters_for_new_record
986
+ prefix << descriptions_for_attribute_setters_for_new_record
974
987
 
975
- prefix << ", the matcher expected the new #{model.name} to be"
976
-
977
- prefix
988
+ prefix << ", the matcher expected the new #{model.name} to be"
989
+ end
978
990
  end
979
991
 
980
992
  def attribute_changed_value_message
@@ -24,6 +24,8 @@ require 'shoulda/matchers/active_record/define_enum_for_matcher'
24
24
  require 'shoulda/matchers/active_record/uniqueness'
25
25
  require 'shoulda/matchers/active_record/validate_uniqueness_of_matcher'
26
26
  require 'shoulda/matchers/active_record/have_attached_matcher'
27
+ require 'shoulda/matchers/active_record/normalize_matcher'
28
+ require 'shoulda/matchers/active_record/encrypt_matcher'
27
29
 
28
30
  module Shoulda
29
31
  module Matchers
@@ -18,15 +18,11 @@ module Shoulda
18
18
  end
19
19
 
20
20
  def activate
21
- doubles_by_method_name.each do |_method_name, double|
22
- double.activate
23
- end
21
+ doubles_by_method_name.each_value(&:activate)
24
22
  end
25
23
 
26
24
  def deactivate
27
- doubles_by_method_name.each do |_method_name, double|
28
- double.deactivate
29
- end
25
+ doubles_by_method_name.each_value(&:deactivate)
30
26
  end
31
27
 
32
28
  def calls_by_method_name
@@ -39,15 +39,11 @@ module Shoulda
39
39
  private
40
40
 
41
41
  def activate
42
- double_collections_by_class.each do |_klass, double_collection|
43
- double_collection.activate
44
- end
42
+ double_collections_by_class.each_value(&:activate)
45
43
  end
46
44
 
47
45
  def deactivate
48
- double_collections_by_class.each do |_klass, double_collection|
49
- double_collection.deactivate
50
- end
46
+ double_collections_by_class.each_value(&:deactivate)
51
47
  end
52
48
 
53
49
  def double_collections_by_class
@@ -400,7 +400,7 @@ module Shoulda
400
400
  false
401
401
  rescue NoMethodError => e
402
402
  if e.message =~
403
- /undefined method `#{delegate_method}' for nil:NilClass/
403
+ /undefined method `#{delegate_method}' for nil/
404
404
  false
405
405
  else
406
406
  raise e
@@ -440,22 +440,20 @@ module Shoulda
440
440
  end
441
441
 
442
442
  def formatted_calls_on_delegate_object
443
- string = ''
444
-
445
- if calls_on_delegate_object.any?
446
- string << "\n\n"
447
- calls_on_delegate_object.each_with_index do |call, i|
448
- name = call.method_name
449
- args = call.args.map(&:inspect).join(', ')
450
- string << "#{i + 1}) #{name}(#{args})\n"
443
+ String.new.tap do |string|
444
+ if calls_on_delegate_object.any?
445
+ string << "\n\n"
446
+ calls_on_delegate_object.each_with_index do |call, i|
447
+ name = call.method_name
448
+ args = call.args.map(&:inspect).join(', ')
449
+ string << "#{i + 1}) #{name}(#{args})\n"
450
+ end
451
+ else
452
+ string << ' (none)'
451
453
  end
452
- else
453
- string << ' (none)'
454
- end
455
454
 
456
- string.rstrip!
457
-
458
- string
455
+ string.rstrip!
456
+ end
459
457
  end
460
458
  end
461
459
  end
@@ -1,7 +1,7 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- module RailsShim # rubocop:disable Metrics/ModuleLength
4
+ module RailsShim
5
5
  class << self
6
6
  def action_pack_version
7
7
  Gem::Version.new(::ActionPack::VERSION::STRING)
@@ -9,10 +9,6 @@ module Shoulda
9
9
  Gem::Version.new('0')
10
10
  end
11
11
 
12
- def active_record_gte_6?
13
- Gem::Requirement.new('>= 6').satisfied_by?(active_record_version)
14
- end
15
-
16
12
  def active_record_version
17
13
  Gem::Version.new(::ActiveRecord::VERSION::STRING)
18
14
  rescue NameError
@@ -60,9 +56,10 @@ module Shoulda
60
56
  end
61
57
 
62
58
  def serialized_attributes_for(model)
59
+ type_serialized_defined = Object.const_defined?('ActiveRecord::Type::Serialized')
63
60
  attribute_types_for(model).
64
61
  inject({}) do |hash, (attribute_name, attribute_type)|
65
- if attribute_type.is_a?(::ActiveRecord::Type::Serialized)
62
+ if type_serialized_defined && attribute_type.is_a?(::ActiveRecord::Type::Serialized)
66
63
  hash.merge(attribute_name => attribute_type.coder)
67
64
  else
68
65
  hash
@@ -146,6 +143,10 @@ module Shoulda
146
143
  model.respond_to?(:attribute_types)
147
144
  end
148
145
 
146
+ def validates_column_options?
147
+ Gem::Requirement.new('>= 7.1.0').satisfied_by?(active_record_version)
148
+ end
149
+
149
150
  private
150
151
 
151
152
  def simply_generate_validation_message(
@@ -172,6 +173,7 @@ module Shoulda
172
173
  I18n.translate(primary_translation_key, translate_options)
173
174
  end
174
175
 
176
+ # @private
175
177
  class FakeAttributeType
176
178
  def initialize(model, attribute_name)
177
179
  @model = model
@@ -41,7 +41,7 @@ module Shoulda
41
41
 
42
42
  # @private
43
43
  class Text < ::String
44
- LIST_ITEM_REGEXP = /\A((?:[a-z0-9]+(?:\)|\.)|\*) )/.freeze
44
+ LIST_ITEM_REGEXP = /\A((?:[a-z0-9]+(?:\)|\.)|\*) )/
45
45
 
46
46
  def indented?
47
47
  self =~ /\A +/
@@ -7,10 +7,9 @@ module Shoulda
7
7
  MAXIMUM_LENGTH_OF_VALUE_TO_DISPLAY = 500
8
8
 
9
9
  def self.deconstantize(path)
10
- if (
11
- defined?(ActiveSupport::Inflector) &&
12
- ActiveSupport::Inflector.respond_to?(:deconstantize)
13
- )
10
+ if defined?(ActiveSupport::Inflector) &&
11
+ ActiveSupport::Inflector.respond_to?(:deconstantize)
12
+
14
13
  ActiveSupport::Inflector.deconstantize(path)
15
14
  else
16
15
  path.to_s[0...(path.to_s.rindex('::') || 0)]
@@ -18,10 +17,9 @@ module Shoulda
18
17
  end
19
18
 
20
19
  def self.safe_constantize(camel_cased_word)
21
- if (
22
- defined?(ActiveSupport::Inflector) &&
23
- ActiveSupport::Inflector.respond_to?(:safe_constantize)
24
- )
20
+ if defined?(ActiveSupport::Inflector) &&
21
+ ActiveSupport::Inflector.respond_to?(:safe_constantize)
22
+
25
23
  ActiveSupport::Inflector.safe_constantize(camel_cased_word)
26
24
  else
27
25
  begin
@@ -72,17 +70,17 @@ module Shoulda
72
70
  end
73
71
 
74
72
  def self.inspect_hash(hash)
75
- output = '‹{'
76
-
77
- output << hash.map { |key, value|
78
- if key.is_a?(Symbol)
79
- "#{key}: #{value.inspect}"
80
- else
81
- "#{key.inspect} => #{value.inspect}"
82
- end
83
- }.join(', ')
73
+ String.new('‹{').tap do |output|
74
+ output << hash.map { |key, value|
75
+ if key.is_a?(Symbol)
76
+ "#{key}: #{value.inspect}"
77
+ else
78
+ "#{key.inspect} => #{value.inspect}"
79
+ end
80
+ }.join(', ')
84
81
 
85
- output << '}›'
82
+ output << '}›'
83
+ end
86
84
  end
87
85
 
88
86
  def self.dummy_value_for(column_type, array: false)
@@ -94,7 +92,7 @@ module Shoulda
94
92
  0
95
93
  when :date
96
94
  Date.new(2100, 1, 1)
97
- when :datetime, :timestamp
95
+ when :datetime, :timestamp, :timestamptz
98
96
  DateTime.new(2100, 1, 1)
99
97
  when :time
100
98
  Time.new(2000, 1, 1)
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '5.3.0'.freeze
4
+ VERSION = '6.1.0'.freeze
5
5
  end
6
6
  end
@@ -14,8 +14,8 @@ require 'shoulda/matchers/active_model'
14
14
  require 'shoulda/matchers/active_record'
15
15
  require 'shoulda/matchers/routing'
16
16
 
17
- module Shoulda
18
- module Matchers
17
+ module Shoulda # :nodoc:
18
+ module Matchers # :nodoc:
19
19
  class << self
20
20
  # @private
21
21
  attr_accessor :assertion_exception_class
@@ -36,6 +36,6 @@ Gem::Specification.new do |s|
36
36
  'shoulda-matchers.gemspec']
37
37
  s.require_paths = ['lib']
38
38
 
39
- s.required_ruby_version = '>= 2.6.0'
39
+ s.required_ruby_version = '>= 3.0.5'
40
40
  s.add_dependency('activesupport', '>= 5.2.0')
41
41
  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: 5.3.0
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tammer Saleh
@@ -11,10 +11,10 @@ authors:
11
11
  - Matt Jankowski
12
12
  - Stafford Brunk
13
13
  - Elliot Winkler
14
- autorequire:
14
+ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2022-12-16 00:00:00.000000000 Z
17
+ date: 2024-01-19 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: activesupport
@@ -69,12 +69,12 @@ files:
69
69
  - lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb
70
70
  - lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb
71
71
  - lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb
72
+ - lib/shoulda/matchers/active_model/comparison_matcher.rb
72
73
  - lib/shoulda/matchers/active_model/disallow_value_matcher.rb
73
74
  - lib/shoulda/matchers/active_model/errors.rb
74
75
  - lib/shoulda/matchers/active_model/have_secure_password_matcher.rb
75
76
  - lib/shoulda/matchers/active_model/helpers.rb
76
77
  - lib/shoulda/matchers/active_model/numericality_matchers.rb
77
- - lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb
78
78
  - lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb
79
79
  - lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb
80
80
  - lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb
@@ -88,6 +88,7 @@ files:
88
88
  - lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb
89
89
  - lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb
90
90
  - lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb
91
+ - lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb
91
92
  - lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb
92
93
  - lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb
93
94
  - lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb
@@ -115,6 +116,7 @@ files:
115
116
  - lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb
116
117
  - lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb
117
118
  - lib/shoulda/matchers/active_record/define_enum_for_matcher.rb
119
+ - lib/shoulda/matchers/active_record/encrypt_matcher.rb
118
120
  - lib/shoulda/matchers/active_record/have_attached_matcher.rb
119
121
  - lib/shoulda/matchers/active_record/have_db_column_matcher.rb
120
122
  - lib/shoulda/matchers/active_record/have_db_index_matcher.rb
@@ -122,6 +124,7 @@ files:
122
124
  - lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb
123
125
  - lib/shoulda/matchers/active_record/have_rich_text_matcher.rb
124
126
  - lib/shoulda/matchers/active_record/have_secure_token_matcher.rb
127
+ - lib/shoulda/matchers/active_record/normalize_matcher.rb
125
128
  - lib/shoulda/matchers/active_record/serialize_matcher.rb
126
129
  - lib/shoulda/matchers/active_record/uniqueness.rb
127
130
  - lib/shoulda/matchers/active_record/uniqueness/model.rb
@@ -180,7 +183,7 @@ metadata:
180
183
  documentation_uri: https://matchers.shoulda.io/docs
181
184
  homepage_uri: https://matchers.shoulda.io
182
185
  source_code_uri: https://github.com/thoughtbot/shoulda-matchers
183
- post_install_message:
186
+ post_install_message:
184
187
  rdoc_options: []
185
188
  require_paths:
186
189
  - lib
@@ -188,15 +191,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
191
  requirements:
189
192
  - - ">="
190
193
  - !ruby/object:Gem::Version
191
- version: 2.6.0
194
+ version: 3.0.5
192
195
  required_rubygems_version: !ruby/object:Gem::Requirement
193
196
  requirements:
194
197
  - - ">="
195
198
  - !ruby/object:Gem::Version
196
199
  version: '0'
197
200
  requirements: []
198
- rubygems_version: 3.3.7
199
- signing_key:
201
+ rubygems_version: 3.5.3
202
+ signing_key:
200
203
  specification_version: 4
201
204
  summary: Simple one-liner tests for common Rails functionality
202
205
  test_files: []
@@ -1,136 +0,0 @@
1
- require 'active_support/core_ext/module/delegation'
2
-
3
- module Shoulda
4
- module Matchers
5
- module ActiveModel
6
- module NumericalityMatchers
7
- # @private
8
- class ComparisonMatcher < ValidationMatcher
9
- ERROR_MESSAGES = {
10
- :> => {
11
- label: :greater_than,
12
- assertions: [false, false, true],
13
- },
14
- :>= => {
15
- label: :greater_than_or_equal_to,
16
- assertions: [false, true, true],
17
- },
18
- :< => {
19
- label: :less_than,
20
- assertions: [true, false, false],
21
- },
22
- :<= => {
23
- label: :less_than_or_equal_to,
24
- assertions: [true, true, false],
25
- },
26
- :== => {
27
- label: :equal_to,
28
- assertions: [false, true, false],
29
- },
30
- :!= => {
31
- label: :other_than,
32
- assertions: [true, false, true],
33
- },
34
- }.freeze
35
-
36
- delegate :failure_message, :failure_message_when_negated, to: :submatchers
37
-
38
- def initialize(numericality_matcher, value, operator)
39
- super(nil)
40
- unless numericality_matcher.respond_to? :diff_to_compare
41
- raise ArgumentError, 'numericality_matcher is invalid'
42
- end
43
-
44
- @numericality_matcher = numericality_matcher
45
- @value = value
46
- @operator = operator
47
- @message = ERROR_MESSAGES[operator][:label]
48
- end
49
-
50
- def simple_description
51
- description = ''
52
-
53
- if expects_strict?
54
- description << ' strictly'
55
- end
56
-
57
- description +
58
- "disallow :#{attribute} from being a number that is not " +
59
- "#{comparison_expectation} #{@value}"
60
- end
61
-
62
- def for(attribute)
63
- @attribute = attribute
64
- self
65
- end
66
-
67
- def with_message(message)
68
- @expects_custom_validation_message = true
69
- @message = message
70
- self
71
- end
72
-
73
- def expects_custom_validation_message?
74
- @expects_custom_validation_message
75
- end
76
-
77
- def matches?(subject)
78
- @subject = subject
79
- submatchers.matches?(subject)
80
- end
81
-
82
- def comparison_description
83
- "#{comparison_expectation} #{@value}"
84
- end
85
-
86
- def submatchers
87
- @_submatchers ||= NumericalityMatchers::Submatchers.new(build_submatchers)
88
- end
89
-
90
- private
91
-
92
- def build_submatchers
93
- comparison_combos.map do |diff, submatcher_method_name|
94
- matcher = __send__(submatcher_method_name, diff, nil)
95
- matcher.with_message(@message, values: { count: @value })
96
- matcher
97
- end
98
- end
99
-
100
- def comparison_combos
101
- diffs_to_compare.zip(submatcher_method_names)
102
- end
103
-
104
- def submatcher_method_names
105
- assertions.map do |value|
106
- if value
107
- :allow_value_matcher
108
- else
109
- :disallow_value_matcher
110
- end
111
- end
112
- end
113
-
114
- def assertions
115
- ERROR_MESSAGES[@operator][:assertions]
116
- end
117
-
118
- def diffs_to_compare
119
- diff_to_compare = @numericality_matcher.diff_to_compare
120
- values = [-1, 0, 1].map { |sign| @value + (diff_to_compare * sign) }
121
-
122
- if @numericality_matcher.given_numeric_column?
123
- values
124
- else
125
- values.map(&:to_s)
126
- end
127
- end
128
-
129
- def comparison_expectation
130
- ERROR_MESSAGES[@operator][:label].to_s.tr('_', ' ')
131
- end
132
- end
133
- end
134
- end
135
- end
136
- end