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.
- checksums.yaml +7 -0
- data/giga-safe-box.gemspec +11 -0
- data/shoulda-matchers-8.0.1/LICENSE +22 -0
- data/shoulda-matchers-8.0.1/README.md +567 -0
- data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
- data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
- data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
- metadata +178 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
|
2
|
+
|
|
3
|
+
module Shoulda
|
|
4
|
+
module Matchers
|
|
5
|
+
module ActiveModel
|
|
6
|
+
# @private
|
|
7
|
+
class ComparisonMatcher < ValidationMatcher
|
|
8
|
+
ERROR_MESSAGES = {
|
|
9
|
+
:> => {
|
|
10
|
+
label: :greater_than,
|
|
11
|
+
assertions: [false, false, true],
|
|
12
|
+
},
|
|
13
|
+
:>= => {
|
|
14
|
+
label: :greater_than_or_equal_to,
|
|
15
|
+
assertions: [false, true, true],
|
|
16
|
+
},
|
|
17
|
+
:< => {
|
|
18
|
+
label: :less_than,
|
|
19
|
+
assertions: [true, false, false],
|
|
20
|
+
},
|
|
21
|
+
:<= => {
|
|
22
|
+
label: :less_than_or_equal_to,
|
|
23
|
+
assertions: [true, true, false],
|
|
24
|
+
},
|
|
25
|
+
:== => {
|
|
26
|
+
label: :equal_to,
|
|
27
|
+
assertions: [false, true, false],
|
|
28
|
+
},
|
|
29
|
+
:!= => {
|
|
30
|
+
label: :other_than,
|
|
31
|
+
assertions: [true, false, true],
|
|
32
|
+
},
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
delegate :failure_message, :failure_message_when_negated, to: :comparison_submatchers
|
|
36
|
+
|
|
37
|
+
def initialize(matcher, value, operator)
|
|
38
|
+
super(nil)
|
|
39
|
+
unless matcher.respond_to? :diff_to_compare
|
|
40
|
+
raise ArgumentError, 'matcher is invalid'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
@matcher = matcher
|
|
44
|
+
@value = value
|
|
45
|
+
@operator = operator
|
|
46
|
+
@message = ERROR_MESSAGES[operator][:label]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def simple_description
|
|
50
|
+
description = ''
|
|
51
|
+
|
|
52
|
+
if expects_strict?
|
|
53
|
+
description = ' strictly'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
description +
|
|
57
|
+
"disallow :#{attribute} from being a number that is not " +
|
|
58
|
+
"#{comparison_expectation} #{@value}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def for(attribute)
|
|
62
|
+
@attribute = attribute
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def with_message(message)
|
|
67
|
+
@expects_custom_validation_message = true
|
|
68
|
+
@message = message
|
|
69
|
+
self
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def expects_custom_validation_message?
|
|
73
|
+
@expects_custom_validation_message
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def matches?(subject)
|
|
77
|
+
@subject = subject
|
|
78
|
+
comparison_submatchers.matches?(subject)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def comparison_description
|
|
82
|
+
"#{comparison_expectation} #{@value}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def comparison_submatchers
|
|
86
|
+
@_comparison_submatchers ||=
|
|
87
|
+
NumericalityMatchers::Submatchers.new(build_comparison_submatchers)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def build_comparison_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: option_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 option_value
|
|
119
|
+
if defined?(@_option_value)
|
|
120
|
+
@_option_value
|
|
121
|
+
else
|
|
122
|
+
@_option_value =
|
|
123
|
+
case @value
|
|
124
|
+
when Proc then @value.call(@subject)
|
|
125
|
+
when Symbol then @subject.send(@value)
|
|
126
|
+
else @value
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def diffs_to_compare
|
|
132
|
+
diff_to_compare = @matcher.diff_to_compare
|
|
133
|
+
values = case option_value
|
|
134
|
+
when String then diffs_when_string(diff_to_compare)
|
|
135
|
+
else [-1, 0, 1].map { |sign| option_value + (diff_to_compare * sign) }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if @matcher.given_numeric_column?
|
|
139
|
+
values
|
|
140
|
+
else
|
|
141
|
+
values.map(&:to_s)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def diffs_when_string(diff_to_compare)
|
|
146
|
+
[-1, 0, 1].map do |sign|
|
|
147
|
+
option_value[0..-2] + (option_value[-1].ord + diff_to_compare * sign).chr
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def comparison_expectation
|
|
152
|
+
ERROR_MESSAGES[@operator][:label].to_s.tr('_', ' ')
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module Shoulda
|
|
4
|
+
module Matchers
|
|
5
|
+
module ActiveModel
|
|
6
|
+
# @private
|
|
7
|
+
class DisallowValueMatcher
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
def_delegators(
|
|
11
|
+
:allow_matcher,
|
|
12
|
+
:_after_setting_value,
|
|
13
|
+
:attribute_changed_value_message=,
|
|
14
|
+
:attribute_to_set,
|
|
15
|
+
:description,
|
|
16
|
+
:expects_strict?,
|
|
17
|
+
:failure_message_preface,
|
|
18
|
+
:failure_message_preface=,
|
|
19
|
+
:ignore_interference_by_writer,
|
|
20
|
+
:last_attribute_setter_used,
|
|
21
|
+
:last_value_set,
|
|
22
|
+
:model,
|
|
23
|
+
:simple_description,
|
|
24
|
+
:values_to_preset=,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def initialize(value)
|
|
28
|
+
@allow_matcher = AllowValueMatcher.new(value)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def matches?(subject)
|
|
32
|
+
allow_matcher.does_not_match?(subject)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def does_not_match?(subject)
|
|
36
|
+
allow_matcher.matches?(subject)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def for(attribute)
|
|
40
|
+
allow_matcher.for(attribute)
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def on(context)
|
|
45
|
+
allow_matcher.on(context)
|
|
46
|
+
self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def with_message(message, options = {})
|
|
50
|
+
allow_matcher.with_message(message, options)
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def strict(strict = true)
|
|
55
|
+
allow_matcher.strict(strict)
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def ignoring_interference_by_writer(value = :always)
|
|
60
|
+
allow_matcher.ignoring_interference_by_writer(value)
|
|
61
|
+
self
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def failure_message
|
|
65
|
+
allow_matcher.failure_message_when_negated
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def failure_message_when_negated
|
|
69
|
+
allow_matcher.failure_message
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
protected
|
|
73
|
+
|
|
74
|
+
attr_reader :allow_matcher
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActiveModel
|
|
4
|
+
# @private
|
|
5
|
+
class CouldNotDetermineValueOutsideOfArray < RuntimeError; end
|
|
6
|
+
|
|
7
|
+
# @private
|
|
8
|
+
class NonNullableBooleanError < Shoulda::Matchers::Error
|
|
9
|
+
def self.create(attribute)
|
|
10
|
+
super(attribute:)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_accessor :attribute
|
|
14
|
+
|
|
15
|
+
def message
|
|
16
|
+
<<-EOT.strip
|
|
17
|
+
You have specified that your model's #{attribute} should ensure inclusion of nil.
|
|
18
|
+
However, #{attribute} is a boolean column which does not allow null values.
|
|
19
|
+
Hence, this test will fail and there is no way to make it pass.
|
|
20
|
+
EOT
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @private
|
|
25
|
+
class CouldNotSetPasswordError < Shoulda::Matchers::Error
|
|
26
|
+
def self.create(model)
|
|
27
|
+
super(model:)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
attr_accessor :model
|
|
31
|
+
|
|
32
|
+
def message
|
|
33
|
+
<<-EOT.strip
|
|
34
|
+
The validation failed because your #{model_name} model declares `has_secure_password`, and
|
|
35
|
+
`validate_presence_of` was called on a #{record_name} which has `password` already set to a value.
|
|
36
|
+
Please use a #{record_name} with an empty `password` instead.
|
|
37
|
+
EOT
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def model_name
|
|
43
|
+
model.name
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def record_name
|
|
47
|
+
model_name.humanize.downcase
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActiveModel
|
|
4
|
+
# The `have_secure_password` matcher tests usage of the
|
|
5
|
+
# `has_secure_password` macro.
|
|
6
|
+
#
|
|
7
|
+
# #### Example
|
|
8
|
+
#
|
|
9
|
+
# class User
|
|
10
|
+
# include ActiveModel::Model
|
|
11
|
+
# include ActiveModel::SecurePassword
|
|
12
|
+
# attr_accessor :password
|
|
13
|
+
# attr_accessor :reset_password
|
|
14
|
+
#
|
|
15
|
+
# has_secure_password
|
|
16
|
+
# has_secure_password :reset_password
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# # RSpec
|
|
20
|
+
# RSpec.describe User, type: :model do
|
|
21
|
+
# it { should have_secure_password }
|
|
22
|
+
# it { should have_secure_password(:reset_password) }
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# # Minitest (Shoulda)
|
|
26
|
+
# class UserTest < ActiveSupport::TestCase
|
|
27
|
+
# should have_secure_password
|
|
28
|
+
# should have_secure_password(:reset_password)
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# @return [HaveSecurePasswordMatcher]
|
|
32
|
+
#
|
|
33
|
+
def have_secure_password(attr = :password)
|
|
34
|
+
HaveSecurePasswordMatcher.new(attr)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @private
|
|
38
|
+
class HaveSecurePasswordMatcher
|
|
39
|
+
attr_reader :failure_message
|
|
40
|
+
|
|
41
|
+
CORRECT_PASSWORD = 'aBcDe12345'.freeze
|
|
42
|
+
INCORRECT_PASSWORD = 'password'.freeze
|
|
43
|
+
|
|
44
|
+
MESSAGES = {
|
|
45
|
+
authenticated_incorrect_password: 'expected %{subject} to not'\
|
|
46
|
+
' authenticate an incorrect %{attribute}',
|
|
47
|
+
did_not_authenticate_correct_password: 'expected %{subject} to'\
|
|
48
|
+
' authenticate the correct %{attribute}',
|
|
49
|
+
method_not_found: 'expected %{subject} to respond to %{methods}',
|
|
50
|
+
should_not_have_secure_password: 'expected %{subject} to'\
|
|
51
|
+
' not %{description}!',
|
|
52
|
+
}.freeze
|
|
53
|
+
|
|
54
|
+
def initialize(attribute)
|
|
55
|
+
@attribute = attribute.to_sym
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def description
|
|
59
|
+
"have a secure password, defined on #{@attribute} attribute"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def matches?(subject)
|
|
63
|
+
@subject = subject
|
|
64
|
+
|
|
65
|
+
if failure = validate
|
|
66
|
+
key, params = failure
|
|
67
|
+
@failure_message =
|
|
68
|
+
MESSAGES[key] % { subject: subject.class }.merge(params)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
failure.nil?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def failure_message_when_negated
|
|
75
|
+
MESSAGES[:should_not_have_secure_password] %
|
|
76
|
+
{ subject: @subject.class, description: }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
protected
|
|
80
|
+
|
|
81
|
+
attr_reader :subject
|
|
82
|
+
|
|
83
|
+
def validate
|
|
84
|
+
missing_methods = expected_methods.reject do |m|
|
|
85
|
+
subject.respond_to?(m)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if missing_methods.present?
|
|
89
|
+
[:method_not_found, { methods: missing_methods.to_sentence }]
|
|
90
|
+
else
|
|
91
|
+
subject.send("#{@attribute}=", CORRECT_PASSWORD)
|
|
92
|
+
subject.send("#{@attribute}_confirmation=", CORRECT_PASSWORD)
|
|
93
|
+
|
|
94
|
+
if not subject.send(authenticate_method, CORRECT_PASSWORD)
|
|
95
|
+
[:did_not_authenticate_correct_password,
|
|
96
|
+
{ attribute: @attribute },]
|
|
97
|
+
elsif subject.send(authenticate_method, INCORRECT_PASSWORD)
|
|
98
|
+
[:authenticated_incorrect_password, { attribute: @attribute }]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
def expected_methods
|
|
106
|
+
@_expected_methods ||= %I[
|
|
107
|
+
#{authenticate_method}
|
|
108
|
+
#{@attribute}=
|
|
109
|
+
#{@attribute}_confirmation=
|
|
110
|
+
#{@attribute}_digest
|
|
111
|
+
#{@attribute}_digest=
|
|
112
|
+
]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def authenticate_method
|
|
116
|
+
if @attribute == :password
|
|
117
|
+
:authenticate
|
|
118
|
+
else
|
|
119
|
+
"authenticate_#{@attribute}".to_sym
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActiveModel
|
|
4
|
+
# @private
|
|
5
|
+
module Helpers
|
|
6
|
+
def pretty_error_messages(object)
|
|
7
|
+
format_validation_errors(object.errors)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def format_validation_errors(errors, attr = nil)
|
|
11
|
+
list_items = errors.to_hash.keys.map do |attribute|
|
|
12
|
+
next if attr && attr.to_sym != attribute.to_sym
|
|
13
|
+
|
|
14
|
+
messages = errors[attribute]
|
|
15
|
+
"* #{attribute}: #{messages}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
list_items.join("\n")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def default_error_message(type, options = {})
|
|
22
|
+
model_name = options.delete(:model_name)
|
|
23
|
+
attribute = options.delete(:attribute)
|
|
24
|
+
instance = options.delete(:instance)
|
|
25
|
+
|
|
26
|
+
RailsShim.generate_validation_message(
|
|
27
|
+
instance,
|
|
28
|
+
attribute.to_sym,
|
|
29
|
+
type,
|
|
30
|
+
model_name,
|
|
31
|
+
options,
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module NumericalityMatchers
|
|
5
|
+
# @private
|
|
6
|
+
class EvenNumberMatcher < NumericTypeMatcher
|
|
7
|
+
NON_EVEN_NUMBER_VALUE = 1
|
|
8
|
+
|
|
9
|
+
def simple_description
|
|
10
|
+
description = ''
|
|
11
|
+
|
|
12
|
+
if expects_strict?
|
|
13
|
+
description << 'strictly '
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
description +
|
|
17
|
+
"disallow :#{attribute} from being an odd number"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def allowed_type_adjective
|
|
21
|
+
'even'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def diff_to_compare
|
|
25
|
+
2
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
protected
|
|
29
|
+
|
|
30
|
+
def wrap_disallow_value_matcher(matcher)
|
|
31
|
+
matcher.with_message(:even)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def disallowed_value
|
|
35
|
+
if @numeric_type_matcher.given_numeric_column?
|
|
36
|
+
NON_EVEN_NUMBER_VALUE
|
|
37
|
+
else
|
|
38
|
+
NON_EVEN_NUMBER_VALUE.to_s
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module Shoulda
|
|
4
|
+
module Matchers
|
|
5
|
+
module ActiveModel
|
|
6
|
+
module NumericalityMatchers
|
|
7
|
+
# @private
|
|
8
|
+
class NumericTypeMatcher
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
def_delegators(
|
|
12
|
+
:disallow_value_matcher,
|
|
13
|
+
:expects_custom_validation_message?,
|
|
14
|
+
:expects_strict?,
|
|
15
|
+
:failure_message,
|
|
16
|
+
:failure_message_when_negated,
|
|
17
|
+
:ignore_interference_by_writer,
|
|
18
|
+
:ignoring_interference_by_writer,
|
|
19
|
+
:matches?,
|
|
20
|
+
:does_not_match?,
|
|
21
|
+
:on,
|
|
22
|
+
:strict,
|
|
23
|
+
:with_message,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def initialize(numeric_type_matcher, attribute)
|
|
27
|
+
@numeric_type_matcher = numeric_type_matcher
|
|
28
|
+
@attribute = attribute
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def allowed_type_name
|
|
32
|
+
'number'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def allowed_type_adjective
|
|
36
|
+
''
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def diff_to_compare
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
protected
|
|
44
|
+
|
|
45
|
+
attr_reader :attribute
|
|
46
|
+
|
|
47
|
+
def wrap_disallow_value_matcher(_matcher)
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def disallowed_value
|
|
52
|
+
raise NotImplementedError
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def disallow_value_matcher
|
|
58
|
+
@_disallow_value_matcher ||= DisallowValueMatcher.new(disallowed_value).tap do |matcher|
|
|
59
|
+
matcher.for(attribute)
|
|
60
|
+
wrap_disallow_value_matcher(matcher)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module NumericalityMatchers
|
|
5
|
+
# @private
|
|
6
|
+
class OddNumberMatcher < NumericTypeMatcher
|
|
7
|
+
NON_ODD_NUMBER_VALUE = 2
|
|
8
|
+
|
|
9
|
+
def simple_description
|
|
10
|
+
description = ''
|
|
11
|
+
|
|
12
|
+
if expects_strict?
|
|
13
|
+
description << 'strictly '
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
description +
|
|
17
|
+
"disallow :#{attribute} from being an even number"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def allowed_type_adjective
|
|
21
|
+
'odd'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def diff_to_compare
|
|
25
|
+
2
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
protected
|
|
29
|
+
|
|
30
|
+
def wrap_disallow_value_matcher(matcher)
|
|
31
|
+
matcher.with_message(:odd)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def disallowed_value
|
|
35
|
+
if @numeric_type_matcher.given_numeric_column?
|
|
36
|
+
NON_ODD_NUMBER_VALUE
|
|
37
|
+
else
|
|
38
|
+
NON_ODD_NUMBER_VALUE.to_s
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Shoulda
|
|
2
|
+
module Matchers
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module NumericalityMatchers
|
|
5
|
+
# @private
|
|
6
|
+
class OnlyIntegerMatcher < NumericTypeMatcher
|
|
7
|
+
NON_INTEGER_VALUE = 0.1
|
|
8
|
+
|
|
9
|
+
def simple_description
|
|
10
|
+
description = ''
|
|
11
|
+
|
|
12
|
+
if expects_strict?
|
|
13
|
+
description << ' strictly'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
description + "disallow :#{attribute} from being a decimal number"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def allowed_type_name
|
|
20
|
+
'integer'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def diff_to_compare
|
|
24
|
+
1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
def wrap_disallow_value_matcher(matcher)
|
|
30
|
+
matcher.with_message(:not_an_integer)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def disallowed_value
|
|
34
|
+
if @numeric_type_matcher.given_numeric_column?
|
|
35
|
+
NON_INTEGER_VALUE
|
|
36
|
+
else
|
|
37
|
+
NON_INTEGER_VALUE.to_s
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|