giga-safe-box 0.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 (140) hide show
  1. checksums.yaml +7 -0
  2. data/giga-safe-box.gemspec +11 -0
  3. data/shoulda-matchers-8.0.1/LICENSE +22 -0
  4. data/shoulda-matchers-8.0.1/README.md +567 -0
  5. data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
  6. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
  7. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
  8. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
  9. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
  10. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
  11. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
  12. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
  13. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
  14. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
  15. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
  16. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
  17. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  18. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
  19. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
  20. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
  21. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
  22. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
  23. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
  24. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
  25. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
  26. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
  27. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
  28. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
  29. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
  30. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
  31. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
  32. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
  33. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
  34. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
  35. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
  36. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
  37. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
  38. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
  39. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
  40. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
  41. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
  42. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  43. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
  44. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
  45. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
  46. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
  47. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
  48. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
  49. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
  50. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
  51. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
  52. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
  53. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
  54. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
  55. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
  56. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
  57. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
  58. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
  59. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
  60. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
  61. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
  62. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
  63. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
  64. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
  65. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
  66. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
  67. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
  68. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
  69. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
  70. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
  71. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
  72. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
  73. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
  74. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
  75. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
  76. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  77. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
  78. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
  79. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
  80. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
  81. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
  82. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
  83. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
  84. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  85. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
  86. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
  87. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
  88. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
  89. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
  90. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
  91. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
  92. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
  93. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
  94. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
  95. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
  96. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
  97. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
  98. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
  99. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
  100. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
  101. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
  102. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
  103. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
  104. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
  105. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
  106. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
  107. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
  108. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
  109. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
  110. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  111. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  112. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
  113. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  114. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  115. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  116. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
  117. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
  118. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
  119. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
  120. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
  121. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  122. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  123. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  124. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  125. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  126. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  127. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  128. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
  129. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
  130. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
  131. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
  132. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
  133. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
  134. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
  135. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
  136. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
  137. data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
  138. data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
  139. data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
  140. metadata +178 -0
@@ -0,0 +1,104 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `have_implicit_order_column` matcher tests that the model has `implicit_order_column`
5
+ # assigned to one of the table columns.
6
+ #
7
+ # class Product < ApplicationRecord
8
+ # self.implicit_order_column = :created_at
9
+ # end
10
+ #
11
+ # # RSpec
12
+ # RSpec.describe Product, type: :model do
13
+ # it { should have_implicit_order_column(:created_at) }
14
+ # end
15
+ #
16
+ # # Minitest (Shoulda)
17
+ # class ProductTest < ActiveSupport::TestCase
18
+ # should have_implicit_order_column(:created_at)
19
+ # end
20
+ #
21
+ # @return [HaveImplicitOrderColumnMatcher]
22
+ #
23
+ def have_implicit_order_column(column_name)
24
+ HaveImplicitOrderColumnMatcher.new(column_name)
25
+ end
26
+
27
+ # @private
28
+ class HaveImplicitOrderColumnMatcher
29
+ attr_reader :failure_message
30
+
31
+ def initialize(column_name)
32
+ @column_name = column_name
33
+ end
34
+
35
+ def matches?(subject)
36
+ @subject = subject
37
+ check_column_exists!
38
+ check_implicit_order_column_matches!
39
+ true
40
+ rescue SecondaryCheckFailedError => e
41
+ @failure_message = Shoulda::Matchers.word_wrap(
42
+ "Expected #{model.name} to #{expectation}, " +
43
+ "but that could not be proved: #{e.message}.",
44
+ )
45
+ false
46
+ rescue PrimaryCheckFailedError => e
47
+ @failure_message = Shoulda::Matchers.word_wrap(
48
+ "Expected #{model.name} to #{expectation}, but #{e.message}.",
49
+ )
50
+ false
51
+ end
52
+
53
+ def failure_message_when_negated
54
+ Shoulda::Matchers.word_wrap(
55
+ "Expected #{model.name} not to #{expectation}, but it did.",
56
+ )
57
+ end
58
+
59
+ def description
60
+ expectation
61
+ end
62
+
63
+ private
64
+
65
+ attr_reader :column_name, :subject
66
+
67
+ def check_column_exists!
68
+ matcher = HaveDbColumnMatcher.new(column_name)
69
+
70
+ if !matcher.matches?(@subject)
71
+ raise SecondaryCheckFailedError.new(
72
+ "The :#{model.table_name} table does not have a " +
73
+ ":#{column_name} column",
74
+ )
75
+ end
76
+ end
77
+
78
+ def check_implicit_order_column_matches!
79
+ if model.implicit_order_column.to_s != column_name.to_s
80
+ message =
81
+ if model.implicit_order_column.nil?
82
+ 'implicit_order_column is not set'
83
+ else
84
+ "it is :#{model.implicit_order_column}"
85
+ end
86
+
87
+ raise PrimaryCheckFailedError.new(message)
88
+ end
89
+ end
90
+
91
+ def model
92
+ subject.class
93
+ end
94
+
95
+ def expectation
96
+ "have an implicit_order_column of :#{column_name}"
97
+ end
98
+
99
+ class SecondaryCheckFailedError < StandardError; end
100
+ class PrimaryCheckFailedError < StandardError; end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,95 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `have_readonly_attribute` matcher tests usage of the
5
+ # `attr_readonly` macro.
6
+ #
7
+ # class User < ActiveRecord::Base
8
+ # attr_readonly :password
9
+ # end
10
+ #
11
+ # # RSpec
12
+ # RSpec.describe User, type: :model do
13
+ # it { should have_readonly_attribute(:password) }
14
+ # end
15
+ #
16
+ # # Minitest (Shoulda)
17
+ # class UserTest < ActiveSupport::TestCase
18
+ # should have_readonly_attribute(:password)
19
+ # end
20
+ #
21
+ # #### Multiple attributes
22
+ #
23
+ # You can pass multiple attributes to assert that each one has the
24
+ # validation. Any qualifier chained on the matcher is applied to
25
+ # every attribute uniformly.
26
+ #
27
+ # class User < ActiveRecord::Base
28
+ # attr_readonly :name, :email
29
+ # end
30
+ #
31
+ # # RSpec
32
+ # RSpec.describe User, type: :model do
33
+ # it { should have_readonly_attribute(:name, :email) }
34
+ # end
35
+ #
36
+ # # Minitest (Shoulda)
37
+ # class UserTest < ActiveSupport::TestCase
38
+ # should have_readonly_attribute(:name, :email)
39
+ # end
40
+ #
41
+ # @return [HaveReadonlyAttributeMatcher]
42
+ #
43
+ def have_readonly_attribute(*values)
44
+ MatcherCollection.build(values) { |value| HaveReadonlyAttributeMatcher.new(value) }
45
+ end
46
+
47
+ # @private
48
+ class HaveReadonlyAttributeMatcher
49
+ def initialize(attribute)
50
+ @attribute = attribute.to_s
51
+ end
52
+
53
+ attr_reader :failure_message, :failure_message_when_negated
54
+
55
+ def failure_reason
56
+ @failure_message
57
+ end
58
+
59
+ def matches?(subject)
60
+ @subject = subject
61
+ if readonly_attributes.include?(@attribute)
62
+ @failure_message_when_negated = "Did not expect #{@attribute}"\
63
+ ' to be read-only'
64
+ true
65
+ else
66
+ @failure_message =
67
+ if readonly_attributes.empty?
68
+ "#{class_name} attribute #{@attribute} " <<
69
+ 'is not read-only'
70
+ else
71
+ "#{class_name} is making " <<
72
+ "#{readonly_attributes.to_a.to_sentence} " <<
73
+ "read-only, but not #{@attribute}."
74
+ end
75
+ false
76
+ end
77
+ end
78
+
79
+ def description
80
+ "make #{@attribute} read-only"
81
+ end
82
+
83
+ private
84
+
85
+ def readonly_attributes
86
+ @_readonly_attributes ||= @subject.class.readonly_attributes || []
87
+ end
88
+
89
+ def class_name
90
+ @subject.class.name
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,83 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `have_rich_text` matcher tests usage of the
5
+ # `has_rich_text` macro.
6
+ #
7
+ # #### Example
8
+ #
9
+ # class Post < ActiveRecord
10
+ # has_rich_text :content
11
+ # end
12
+ #
13
+ # # RSpec
14
+ # RSpec.describe Post, type: :model do
15
+ # it { should have_rich_text(:content) }
16
+ # end
17
+ #
18
+ # # Minitest (Shoulda)
19
+ # class PostTest < ActiveSupport::TestCase
20
+ # should have_rich_text(:content)
21
+ # end
22
+ #
23
+ # @return [HaveRichTextMatcher]
24
+ #
25
+ def have_rich_text(rich_text_attribute)
26
+ HaveRichTextMatcher.new(rich_text_attribute)
27
+ end
28
+
29
+ # @private
30
+ class HaveRichTextMatcher
31
+ def initialize(rich_text_attribute)
32
+ @rich_text_attribute = rich_text_attribute
33
+ end
34
+
35
+ def description
36
+ "have configured :#{rich_text_attribute} as a "\
37
+ 'ActionText::RichText association'
38
+ end
39
+
40
+ def failure_message
41
+ "Expected #{subject.class} to #{error_description}"
42
+ end
43
+
44
+ def failure_message_when_negated
45
+ "Did not expect #{subject.class} to have ActionText::RichText"\
46
+ " :#{rich_text_attribute}"
47
+ end
48
+
49
+ def matches?(subject)
50
+ @subject = subject
51
+ @error = run_checks
52
+ @error.nil?
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :error, :rich_text_attribute, :subject
58
+
59
+ def run_checks
60
+ if !has_attribute?
61
+ ":#{rich_text_attribute} does not exist"
62
+ elsif !has_expected_action_text?
63
+ :default
64
+ end
65
+ end
66
+
67
+ def has_attribute?
68
+ @subject.respond_to?(rich_text_attribute.to_s)
69
+ end
70
+
71
+ def has_expected_action_text?
72
+ defined?(ActionText::RichText) &&
73
+ @subject.send(rich_text_attribute).
74
+ is_a?(ActionText::RichText)
75
+ end
76
+
77
+ def error_description
78
+ error == :default ? description : "#{description} but #{error}"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,132 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `have_secure_token` matcher tests usage of the
5
+ # `has_secure_token` macro.
6
+ #
7
+ # class User < ActiveRecord
8
+ # has_secure_token
9
+ # has_secure_token :auth_token
10
+ # end
11
+ #
12
+ # # RSpec
13
+ # RSpec.describe User, type: :model do
14
+ # it { should have_secure_token }
15
+ # it { should have_secure_token(:auth_token) }
16
+ # end
17
+ #
18
+ # # Minitest (Shoulda)
19
+ # class UserTest < ActiveSupport::TestCase
20
+ # should have_secure_token
21
+ # should have_secure_token(:auth_token)
22
+ # end
23
+ #
24
+ # #### Qualifiers
25
+ #
26
+ # ##### ignoring_check_for_db_index
27
+ #
28
+ # By default, this matcher tests that an index is defined on your token
29
+ # column. Use `ignoring_check_for_db_index` if this is not the case.
30
+ #
31
+ # class User < ActiveRecord
32
+ # has_secure_token :auth_token
33
+ # end
34
+ #
35
+ # # RSpec
36
+ # RSpec.describe User, type: :model do
37
+ # it { should have_secure_token(:auth_token).ignoring_check_for_db_index }
38
+ # end
39
+ #
40
+ # # Minitest (Shoulda)
41
+ # class UserTest < ActiveSupport::TestCase
42
+ # should have_secure_token(:auth_token).ignoring_check_for_db_index
43
+ # end
44
+ #
45
+ # @return [HaveSecureToken]
46
+ #
47
+ def have_secure_token(token_attribute = :token)
48
+ HaveSecureTokenMatcher.new(token_attribute)
49
+ end
50
+
51
+ # @private
52
+ class HaveSecureTokenMatcher
53
+ attr_reader :token_attribute
54
+
55
+ def initialize(token_attribute)
56
+ @token_attribute = token_attribute
57
+ @options = { ignore_check_for_db_index: false }
58
+ end
59
+
60
+ def description
61
+ "have :#{token_attribute} as a secure token"
62
+ end
63
+
64
+ def failure_message
65
+ return if !@errors
66
+
67
+ "Expected #{@subject.class} to #{description} but the following " \
68
+ "errors were found: #{@errors.join(', ')}"
69
+ end
70
+
71
+ def failure_message_when_negated
72
+ return if !@errors
73
+
74
+ "Did not expect #{@subject.class} to have secure token " \
75
+ ":#{token_attribute}"
76
+ end
77
+
78
+ def matches?(subject)
79
+ @subject = subject
80
+ @errors = run_checks
81
+ @errors.empty?
82
+ end
83
+
84
+ def ignoring_check_for_db_index
85
+ @options[:ignore_check_for_db_index] = true
86
+ self
87
+ end
88
+
89
+ private
90
+
91
+ def run_checks
92
+ @errors = []
93
+ if !has_expected_instance_methods?
94
+ @errors << 'missing expected class and instance methods'
95
+ end
96
+ if !has_expected_db_column?
97
+ @errors << "missing correct column #{token_attribute}:string"
98
+ end
99
+ if !@options[:ignore_check_for_db_index] && !has_expected_db_index?
100
+ @errors << "missing unique index for #{table_and_column}"
101
+ end
102
+ @errors
103
+ end
104
+
105
+ def has_expected_instance_methods?
106
+ @subject.respond_to?(token_attribute.to_s) &&
107
+ @subject.respond_to?("#{token_attribute}=") &&
108
+ @subject.respond_to?("regenerate_#{token_attribute}") &&
109
+ @subject.class.respond_to?(:generate_unique_secure_token)
110
+ end
111
+
112
+ def has_expected_db_column?
113
+ matcher = HaveDbColumnMatcher.new(token_attribute).of_type(:string)
114
+ matcher.matches?(@subject)
115
+ end
116
+
117
+ def has_expected_db_index?
118
+ matcher = HaveDbIndexMatcher.new(token_attribute).unique(true)
119
+ matcher.matches?(@subject)
120
+ end
121
+
122
+ def table_and_column
123
+ "#{table_name}.#{token_attribute}"
124
+ end
125
+
126
+ def table_name
127
+ @subject.class.table_name
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,151 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `normalize` matcher is used to ensure attribute normalizations
5
+ # are transforming attribute values as expected.
6
+ #
7
+ # Take this model for example:
8
+ #
9
+ # class User < ActiveRecord::Base
10
+ # normalizes :email, with: -> email { email.strip.downcase }
11
+ # end
12
+ #
13
+ # You can use `normalize` providing an input and defining the expected
14
+ # normalization output:
15
+ #
16
+ # # RSpec
17
+ # RSpec.describe User, type: :model do
18
+ # it do
19
+ # should normalize(:email).from(" ME@XYZ.COM\n").to("me@xyz.com")
20
+ # end
21
+ # end
22
+ #
23
+ # # Minitest (Shoulda)
24
+ # class User < ActiveSupport::TestCase
25
+ # should normalize(:email).from(" ME@XYZ.COM\n").to("me@xyz.com")
26
+ # end
27
+ #
28
+ # You can use `normalize` to test multiple attributes at once:
29
+ #
30
+ # class User < ActiveRecord::Base
31
+ # normalizes :email, :handle, with: -> value { value.strip.downcase }
32
+ # end
33
+ #
34
+ # # RSpec
35
+ # RSpec.describe User, type: :model do
36
+ # it do
37
+ # should normalize(:email, :handle).from(" Example\n").to("example")
38
+ # end
39
+ # end
40
+ #
41
+ # # Minitest (Shoulda)
42
+ # class User < ActiveSupport::TestCase
43
+ # should normalize(:email, :handle).from(" Example\n").to("example")
44
+ # end
45
+ #
46
+ # If the normalization accepts nil values with the `apply_to_nil` option,
47
+ # you just need to use `.from(nil).to("Your expected value here")`.
48
+ #
49
+ # class User < ActiveRecord::Base
50
+ # normalizes :name, with: -> name { name&.titleize || 'Untitled' },
51
+ # apply_to_nil: true
52
+ # end
53
+ #
54
+ # # RSpec
55
+ # RSpec.describe User, type: :model do
56
+ # it { should normalize(:name).from("jane doe").to("Jane Doe") }
57
+ # it { should normalize(:name).from(nil).to("Untitled") }
58
+ # end
59
+ #
60
+ # # Minitest (Shoulda)
61
+ # class User < ActiveSupport::TestCase
62
+ # should normalize(:name).from("jane doe").to("Jane Doe")
63
+ # should normalize(:name).from(nil).to("Untitled")
64
+ # end
65
+ #
66
+ # @return [NormalizeMatcher]
67
+ #
68
+ def normalize(*attributes)
69
+ if attributes.empty?
70
+ raise ArgumentError, 'need at least one attribute'
71
+ else
72
+ NormalizeMatcher.new(*attributes)
73
+ end
74
+ end
75
+
76
+ # @private
77
+ class NormalizeMatcher
78
+ attr_reader :attributes, :from_value, :to_value, :failure_message,
79
+ :failure_message_when_negated
80
+
81
+ def initialize(*attributes)
82
+ @attributes = attributes
83
+ end
84
+
85
+ def description
86
+ %(
87
+ normalize #{attributes.to_sentence(last_word_connector: ' and ')} from
88
+ ‹#{from_value.inspect}› to ‹#{to_value.inspect}›
89
+ ).squish
90
+ end
91
+
92
+ def from(value)
93
+ @from_value = value
94
+
95
+ self
96
+ end
97
+
98
+ def to(value)
99
+ @to_value = value
100
+
101
+ self
102
+ end
103
+
104
+ def matches?(subject)
105
+ attributes.all? { |attribute| attribute_matches?(subject, attribute) }
106
+ end
107
+
108
+ def does_not_match?(subject)
109
+ attributes.all? { |attribute| attribute_does_not_match?(subject, attribute) }
110
+ end
111
+
112
+ private
113
+
114
+ def attribute_matches?(subject, attribute)
115
+ return true if normalize_attribute?(subject, attribute)
116
+
117
+ @failure_message = build_failure_message(
118
+ attribute,
119
+ subject.class.normalize_value_for(attribute, from_value),
120
+ )
121
+ false
122
+ end
123
+
124
+ def attribute_does_not_match?(subject, attribute)
125
+ return true unless normalize_attribute?(subject, attribute)
126
+
127
+ @failure_message_when_negated = build_failure_message_when_negated(attribute)
128
+ false
129
+ end
130
+
131
+ def normalize_attribute?(subject, attribute)
132
+ subject.class.normalize_value_for(attribute, from_value) == to_value
133
+ end
134
+
135
+ def build_failure_message(attribute, attribute_value)
136
+ %(
137
+ Expected to normalize #{attribute.inspect} from ‹#{from_value.inspect}› to
138
+ ‹#{to_value.inspect}› but it was normalized to ‹#{attribute_value.inspect}›
139
+ ).squish
140
+ end
141
+
142
+ def build_failure_message_when_negated(attribute)
143
+ %(
144
+ Expected to not normalize #{attribute.inspect} from ‹#{from_value.inspect}› to
145
+ ‹#{to_value.inspect}› but it was normalized
146
+ ).squish
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end