shoulda-matchers 3.1.3 → 4.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound/ruby.yml +336 -316
- data/.python-version +1 -0
- data/.rubocop.yml +3 -1
- data/.travis.yml +7 -6
- data/Appraisals +76 -44
- data/CONTRIBUTING.md +137 -66
- data/Gemfile +5 -5
- data/Gemfile.lock +30 -35
- data/MAINTAINING.md +250 -0
- data/MIT-LICENSE +1 -1
- data/NEWS.md +176 -4
- data/README.md +138 -200
- data/Rakefile +7 -0
- data/bin/setup +190 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +4 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -6
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -17
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +27 -0
- data/gemfiles/4.2.gemfile +21 -20
- data/gemfiles/4.2.gemfile.lock +143 -140
- data/gemfiles/5.0.gemfile +37 -0
- data/gemfiles/5.0.gemfile.lock +238 -0
- data/gemfiles/5.1.gemfile +38 -0
- data/gemfiles/5.1.gemfile.lock +254 -0
- data/gemfiles/5.2.gemfile +40 -0
- data/gemfiles/5.2.gemfile.lock +273 -0
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +18 -6
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -1
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +87 -27
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +1 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +0 -4
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +5 -0
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -0
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +26 -11
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +39 -4
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +116 -47
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +127 -38
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +55 -37
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +30 -1
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +11 -4
- data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +11 -6
- data/lib/shoulda/matchers/active_record.rb +3 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +172 -22
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +11 -6
- data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +46 -0
- data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +51 -0
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +268 -38
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +111 -0
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +207 -79
- data/lib/shoulda/matchers/doublespeak/object_double.rb +5 -1
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +100 -21
- data/lib/shoulda/matchers/rails_shim.rb +133 -52
- data/lib/shoulda/matchers/routing.rb +2 -2
- data/lib/shoulda/matchers/util.rb +23 -1
- data/lib/shoulda/matchers/util/word_wrap.rb +6 -2
- data/lib/shoulda/matchers/version.rb +1 -1
- data/script/install_gems_in_all_appraisals +3 -1
- data/script/run_all_tests +3 -1
- data/script/supported_ruby_versions +7 -0
- data/script/update_gem_in_all_appraisals +3 -1
- data/script/update_gems_in_all_appraisals +3 -1
- data/shoulda-matchers.gemspec +3 -3
- data/spec/acceptance/independent_matchers_spec.rb +2 -2
- data/spec/acceptance/multiple_libraries_integration_spec.rb +1 -1
- data/spec/acceptance/rails_integration_spec.rb +2 -2
- data/spec/spec_helper.rb +2 -3
- data/spec/support/acceptance/helpers.rb +2 -0
- data/spec/support/acceptance/helpers/command_helpers.rb +17 -4
- data/spec/support/acceptance/helpers/rails_migration_helpers.rb +21 -0
- data/spec/support/acceptance/helpers/step_helpers.rb +1 -1
- data/spec/support/tests/current_bundle.rb +3 -9
- data/spec/support/tests/filesystem.rb +2 -2
- data/spec/support/unit/attribute.rb +0 -2
- data/spec/support/unit/capture.rb +9 -3
- data/spec/support/unit/helpers/action_pack_versions.rb +22 -0
- data/spec/support/unit/helpers/active_model_versions.rb +4 -0
- data/spec/support/unit/helpers/active_record_versions.rb +22 -2
- data/spec/support/unit/helpers/active_resource_builder.rb +2 -2
- data/spec/support/unit/helpers/controller_builder.rb +1 -1
- data/spec/support/unit/helpers/message_helpers.rb +19 -0
- data/spec/support/unit/helpers/rails_versions.rb +14 -0
- data/spec/support/unit/matchers/fail_with_message_matcher.rb +7 -5
- data/spec/support/unit/matchers/print_warning_including.rb +21 -13
- data/spec/support/unit/model_creation_strategies/active_record.rb +1 -1
- data/spec/support/unit/model_creators/active_record.rb +0 -1
- data/spec/support/unit/model_creators/basic.rb +7 -2
- data/spec/support/unit/rails_application.rb +25 -0
- data/spec/support/unit/record_validating_confirmation_builder.rb +5 -2
- data/spec/support/unit/validation_matcher_scenario.rb +0 -2
- data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +18 -18
- data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +33 -5
- data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +1 -1
- data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +80 -78
- data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +7 -9
- data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +28 -4
- data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +19 -1
- data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +27 -4
- data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +62 -5
- data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +52 -18
- data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +51 -4
- data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +99 -71
- data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +41 -15
- data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +445 -15
- data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +615 -93
- data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +169 -0
- data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +167 -97
- data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +2 -4
- data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +152 -19
- data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +258 -94
- data/spec/unit_spec_helper.rb +9 -1
- data/zeus.json +1 -1
- metadata +31 -16
- data/gemfiles/4.0.0.gemfile +0 -38
- data/gemfiles/4.0.0.gemfile.lock +0 -223
- data/gemfiles/4.0.1.gemfile +0 -38
- data/gemfiles/4.0.1.gemfile.lock +0 -225
- data/gemfiles/4.1.gemfile +0 -38
- data/gemfiles/4.1.gemfile.lock +0 -220
- data/script/SUPPORTED_VERSIONS +0 -1
@@ -815,16 +815,14 @@ value", but that attribute does not exist.
|
|
815
815
|
end
|
816
816
|
end
|
817
817
|
|
818
|
-
|
819
|
-
context '
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
enum status: { pending: 1, shipped: 2, delivered: 3 }
|
824
|
-
end
|
825
|
-
|
826
|
-
expect(model.new).to allow_value(1).for(:status)
|
818
|
+
context 'given an ActiveRecord model' do
|
819
|
+
context 'where the attribute under test is an enum and the given value is a value in that enum' do
|
820
|
+
it 'accepts' do
|
821
|
+
model = define_model('Shipment', status: :integer) do
|
822
|
+
enum status: { pending: 1, shipped: 2, delivered: 3 }
|
827
823
|
end
|
824
|
+
|
825
|
+
expect(model.new).to allow_value(1).for(:status)
|
828
826
|
end
|
829
827
|
end
|
830
828
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model do
|
4
|
-
if
|
4
|
+
if active_model_supports_absence_validation?
|
5
5
|
def self.available_column_types
|
6
6
|
[
|
7
7
|
:string,
|
@@ -48,6 +48,27 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
context 'when used in the negative' do
|
52
|
+
it 'fails' do
|
53
|
+
assertion = lambda do
|
54
|
+
expect(validating_absence_of(:attr)).
|
55
|
+
not_to validate_absence_of(:attr)
|
56
|
+
end
|
57
|
+
|
58
|
+
message = <<-MESSAGE
|
59
|
+
Expected Example not to validate that :attr is empty/falsy, but this
|
60
|
+
could not be proved.
|
61
|
+
After setting :attr to ‹"an arbitrary value"›, the matcher expected
|
62
|
+
the Example to be valid, but it was invalid instead, producing these
|
63
|
+
validation errors:
|
64
|
+
|
65
|
+
* attr: ["must be blank"]
|
66
|
+
MESSAGE
|
67
|
+
|
68
|
+
expect(&assertion).to fail_with_message(message)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
51
72
|
def validation_matcher_scenario_args
|
52
73
|
super.deep_merge(model_creator: :active_record)
|
53
74
|
end
|
@@ -58,7 +79,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateAbsenceOfMatcher, type: :model
|
|
58
79
|
record = define_model(:example, attr: :string).new
|
59
80
|
|
60
81
|
message = <<-MESSAGE
|
61
|
-
Example
|
82
|
+
Expected Example to validate that :attr is empty/falsy, but this could
|
83
|
+
not be proved.
|
62
84
|
After setting :attr to ‹"an arbitrary value"›, the matcher expected
|
63
85
|
the Example to be invalid, but it was valid instead.
|
64
86
|
MESSAGE
|
@@ -97,7 +119,8 @@ Example did not properly validate that :attr is empty/falsy.
|
|
97
119
|
context 'an ActiveModel class without an absence validation' do
|
98
120
|
it 'rejects with the correct failure message' do
|
99
121
|
message = <<-MESSAGE
|
100
|
-
Example
|
122
|
+
Expected Example to validate that :attr is empty/falsy, but this could
|
123
|
+
not be proved.
|
101
124
|
After setting :attr to ‹"an arbitrary value"›, the matcher expected
|
102
125
|
the Example to be invalid, but it was valid instead.
|
103
126
|
MESSAGE
|
@@ -161,7 +184,8 @@ Example did not properly validate that :attr is empty/falsy.
|
|
161
184
|
model = having_and_belonging_to_many(:children, absence: false)
|
162
185
|
|
163
186
|
message = <<-MESSAGE
|
164
|
-
Parent
|
187
|
+
Expected Parent to validate that :children is empty/falsy, but this
|
188
|
+
could not be proved.
|
165
189
|
After setting :children to ‹[#<Child id: nil>]›, the matcher expected
|
166
190
|
the Parent to be invalid, but it was valid instead.
|
167
191
|
MESSAGE
|
@@ -21,7 +21,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateAcceptanceOfMatcher, type: :mod
|
|
21
21
|
attribute_name: :attr,
|
22
22
|
changing_values_with: :always_nil,
|
23
23
|
expected_message: <<-MESSAGE.strip
|
24
|
-
Example
|
24
|
+
Expected Example to validate that :attr has been set to "1", but this
|
25
|
+
could not be proved.
|
25
26
|
After setting :attr to ‹false› -- which was read back as ‹nil› -- the
|
26
27
|
matcher expected the Example to be invalid, but it was valid instead.
|
27
28
|
|
@@ -35,6 +36,23 @@ Example did not properly validate that :attr has been set to "1".
|
|
35
36
|
},
|
36
37
|
model_creator: :active_model
|
37
38
|
)
|
39
|
+
|
40
|
+
it 'fails when used in the negative' do
|
41
|
+
assertion = lambda do
|
42
|
+
expect(record_validating_acceptance).not_to matcher
|
43
|
+
end
|
44
|
+
|
45
|
+
message = <<-MESSAGE
|
46
|
+
Expected Example not to validate that :attr has been set to "1", but
|
47
|
+
this could not be proved.
|
48
|
+
After setting :attr to ‹false›, the matcher expected the Example to be
|
49
|
+
valid, but it was invalid instead, producing these validation errors:
|
50
|
+
|
51
|
+
* attr: ["must be accepted"]
|
52
|
+
MESSAGE
|
53
|
+
|
54
|
+
expect(&assertion).to fail_with_message(message)
|
55
|
+
end
|
38
56
|
end
|
39
57
|
|
40
58
|
context 'a model without an acceptance validation' do
|
@@ -36,8 +36,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateConfirmationOfMatcher, type: :m
|
|
36
36
|
attribute_name: :password,
|
37
37
|
changing_values_with: :next_value,
|
38
38
|
expected_message: <<-MESSAGE.strip
|
39
|
-
Example
|
40
|
-
:password.
|
39
|
+
Expected Example to validate that :password_confirmation matches
|
40
|
+
:password, but this could not be proved.
|
41
41
|
After setting :password_confirmation to ‹"same value"›, then setting
|
42
42
|
:password to ‹"same value"› -- which was read back as ‹"same valuf"›
|
43
43
|
-- the matcher expected the Example to be valid, but it was invalid
|
@@ -55,6 +55,29 @@ Example did not properly validate that :password_confirmation matches
|
|
55
55
|
},
|
56
56
|
model_creator: :active_model
|
57
57
|
)
|
58
|
+
|
59
|
+
it 'fails when used in the negative' do
|
60
|
+
builder = builder_for_record_validating_confirmation(
|
61
|
+
model_name: 'Example',
|
62
|
+
attribute: :password,
|
63
|
+
confirmation_attribute: :password_confirmation
|
64
|
+
)
|
65
|
+
|
66
|
+
assertion = lambda do
|
67
|
+
expect(builder.record).
|
68
|
+
not_to validate_confirmation_of(builder.attribute_to_confirm)
|
69
|
+
end
|
70
|
+
|
71
|
+
message = <<-MESSAGE
|
72
|
+
Expected Example not to validate that :password_confirmation matches
|
73
|
+
:password, but this could not be proved.
|
74
|
+
After setting :password_confirmation to ‹nil›, then setting :password
|
75
|
+
to ‹"any value"›, the matcher expected the Example to be invalid, but
|
76
|
+
it was valid instead.
|
77
|
+
MESSAGE
|
78
|
+
|
79
|
+
expect(&assertion).to fail_with_message(message)
|
80
|
+
end
|
58
81
|
end
|
59
82
|
|
60
83
|
context 'when the model does not have a confirmation attribute' do
|
@@ -108,8 +131,8 @@ The matcher attempted to set :attribute_to_confirm on the Example to
|
|
108
131
|
end
|
109
132
|
|
110
133
|
message = <<-MESSAGE
|
111
|
-
Example
|
112
|
-
|
134
|
+
Expected Example to validate that :attribute_to_confirm_confirmation
|
135
|
+
matches :attribute_to_confirm, but this could not be proved.
|
113
136
|
After setting :attribute_to_confirm_confirmation to ‹"some value"›,
|
114
137
|
then setting :attribute_to_confirm to ‹"different value"›, the matcher
|
115
138
|
expected the Example to be invalid, but it was valid instead.
|
@@ -7,11 +7,26 @@ describe Shoulda::Matchers::ActiveModel::ValidateExclusionOfMatcher, type: :mode
|
|
7
7
|
to validate_exclusion_of(:attr).in_range(2..5)
|
8
8
|
end
|
9
9
|
|
10
|
-
it 'rejects
|
10
|
+
it 'rejects if the given range spills past the top of the range in the validation' do
|
11
11
|
expect(validating_exclusion(in: 2..5)).
|
12
12
|
not_to validate_exclusion_of(:attr).in_range(2..6)
|
13
13
|
end
|
14
14
|
|
15
|
+
it 'rejects if the given range falls short of the top of the range in the validation' do
|
16
|
+
expect(validating_exclusion(in: 2..5)).
|
17
|
+
not_to validate_exclusion_of(:attr).in_range(2..4)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'rejects if the given range spills past the bottom of the range in the validation' do
|
21
|
+
expect(validating_exclusion(in: 2..5)).
|
22
|
+
not_to validate_exclusion_of(:attr).in_range(1..5)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'rejects if the given range falls short of the bottom of the range in the validation' do
|
26
|
+
expect(validating_exclusion(in: 2..5)).
|
27
|
+
not_to validate_exclusion_of(:attr).in_range(3..5)
|
28
|
+
end
|
29
|
+
|
15
30
|
it 'does not override the default message with a blank' do
|
16
31
|
expect(validating_exclusion(in: 2..5)).
|
17
32
|
to validate_exclusion_of(:attr).in_range(2..5).with_message(nil)
|
@@ -25,8 +40,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateExclusionOfMatcher, type: :mode
|
|
25
40
|
attribute_name: :attr,
|
26
41
|
changing_values_with: :next_value,
|
27
42
|
expected_message: <<-MESSAGE.strip
|
28
|
-
Example
|
29
|
-
|
43
|
+
Expected Example to validate that :attr lies outside the range ‹2› to
|
44
|
+
‹5›, but this could not be proved.
|
30
45
|
After setting :attr to ‹1› -- which was read back as ‹2› -- the
|
31
46
|
matcher expected the Example to be valid, but it was invalid instead,
|
32
47
|
producing these validation errors:
|
@@ -51,6 +66,22 @@ to ‹5›.
|
|
51
66
|
matcher.in_range(2..5)
|
52
67
|
end
|
53
68
|
end
|
69
|
+
|
70
|
+
it 'fails when used in the negative' do
|
71
|
+
assertion = lambda do
|
72
|
+
expect(validating_exclusion(in: 2..5)).
|
73
|
+
not_to validate_exclusion_of(:attr).in_range(2..5)
|
74
|
+
end
|
75
|
+
|
76
|
+
message = <<-MESSAGE
|
77
|
+
Expected Example not to validate that :attr lies outside the range ‹2›
|
78
|
+
to ‹5›, but this could not be proved.
|
79
|
+
After setting :attr to ‹6›, the matcher expected the Example to be
|
80
|
+
invalid, but it was valid instead.
|
81
|
+
MESSAGE
|
82
|
+
|
83
|
+
expect(&assertion).to fail_with_message(message)
|
84
|
+
end
|
54
85
|
end
|
55
86
|
|
56
87
|
context 'an attribute which must be excluded from a range with excluded end' do
|
@@ -70,6 +101,14 @@ to ‹5›.
|
|
70
101
|
expect(validating_exclusion(in: 2..4, message: 'not good')).
|
71
102
|
to validate_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
|
72
103
|
end
|
104
|
+
|
105
|
+
it 'accepts ensuring the correct range with an interpolated variable in the message' do
|
106
|
+
matcher = validating_exclusion(in: 2..4, message: '%{value} is not good')
|
107
|
+
expect(matcher).
|
108
|
+
to validate_exclusion_of(:attr).
|
109
|
+
in_range(2..4).
|
110
|
+
with_message(/^[234] is not good$/)
|
111
|
+
end
|
73
112
|
end
|
74
113
|
|
75
114
|
context 'an attribute with custom range validations' do
|
@@ -153,8 +192,8 @@ to ‹5›.
|
|
153
192
|
attribute_name: :attr,
|
154
193
|
changing_values_with: :next_value,
|
155
194
|
expected_message: <<-MESSAGE.strip
|
156
|
-
Example
|
157
|
-
|
195
|
+
Expected Example to validate that :attr is neither ‹"one"› nor ‹"two"›,
|
196
|
+
but this could not be proved.
|
158
197
|
After setting :attr to ‹"one"› -- which was read back as ‹"onf"› --
|
159
198
|
the matcher expected the Example to be invalid, but it was valid
|
160
199
|
instead.
|
@@ -178,6 +217,24 @@ Example did not properly validate that :attr is neither ‹"one"› nor
|
|
178
217
|
end
|
179
218
|
end
|
180
219
|
|
220
|
+
it 'fails when used in the negative' do
|
221
|
+
assertion = lambda do
|
222
|
+
expect(validating_exclusion(in: %w(one two))).
|
223
|
+
not_to validate_exclusion_of(:attr).in_array(%w(one two))
|
224
|
+
end
|
225
|
+
|
226
|
+
message = <<-MESSAGE
|
227
|
+
Expected Example not to validate that :attr is neither ‹"one"› nor
|
228
|
+
‹"two"›, but this could not be proved.
|
229
|
+
After setting :attr to ‹"two"›, the matcher expected the Example to be
|
230
|
+
valid, but it was invalid instead, producing these validation errors:
|
231
|
+
|
232
|
+
* attr: ["is reserved"]
|
233
|
+
MESSAGE
|
234
|
+
|
235
|
+
expect(&assertion).to fail_with_message(message)
|
236
|
+
end
|
237
|
+
|
181
238
|
def define_model_validating_exclusion(options)
|
182
239
|
options = options.dup
|
183
240
|
column_type = options.delete(:column_type) { :string }
|
@@ -25,7 +25,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
25
25
|
it_behaves_like 'it supports in_array',
|
26
26
|
possible_values: (1..5).to_a,
|
27
27
|
zero: 0,
|
28
|
-
reserved_outside_value: described_class::
|
28
|
+
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_INTEGER
|
29
29
|
|
30
30
|
it_behaves_like 'it supports in_range',
|
31
31
|
possible_values: 1..5,
|
@@ -82,7 +82,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
82
82
|
it_behaves_like 'it supports in_array',
|
83
83
|
possible_values: [1.0, 2.0, 3.0, 4.0, 5.0],
|
84
84
|
zero: 0.0,
|
85
|
-
reserved_outside_value: described_class::
|
85
|
+
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_INTEGER
|
86
86
|
|
87
87
|
it_behaves_like 'it supports in_range',
|
88
88
|
possible_values: 1.0..5.0,
|
@@ -192,20 +192,19 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
192
192
|
end
|
193
193
|
|
194
194
|
context 'against a time attribute' do
|
195
|
-
|
195
|
+
default_time = Time.zone.local(2000, 1, 1)
|
196
196
|
|
197
|
-
define_method(:
|
197
|
+
define_method(:default_time) { default_time }
|
198
198
|
|
199
199
|
it_behaves_like 'it supports in_array',
|
200
|
-
possible_values: (1..
|
201
|
-
reserved_outside_value: described_class::ARBITRARY_OUTSIDE_TIME
|
200
|
+
possible_values: (1..3).map { |hour| default_time.change(hour: hour) }
|
202
201
|
|
203
202
|
it_behaves_like 'it supports in_range',
|
204
|
-
possible_values: (
|
203
|
+
possible_values: (default_time.change(hour: 1) .. default_time.change(hour: 3))
|
205
204
|
|
206
205
|
define_method :build_object do |options = {}, &block|
|
207
206
|
build_object_with_generic_attribute(
|
208
|
-
options.merge(column_type: :time, value:
|
207
|
+
options.merge(column_type: :time, value: default_time),
|
209
208
|
&block
|
210
209
|
)
|
211
210
|
end
|
@@ -215,7 +214,7 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
215
214
|
end
|
216
215
|
|
217
216
|
def validation_matcher_scenario_args
|
218
|
-
super.deep_merge(column_type: :time, default_value:
|
217
|
+
super.deep_merge(column_type: :time, default_value: default_time)
|
219
218
|
end
|
220
219
|
end
|
221
220
|
|
@@ -368,6 +367,17 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
368
367
|
end
|
369
368
|
end
|
370
369
|
|
370
|
+
it 'matches when validation uses given message that has an interpolated variable' do
|
371
|
+
builder = build_object_allowing(
|
372
|
+
valid_values,
|
373
|
+
validation_options: { message: '%{value} is not included' },
|
374
|
+
)
|
375
|
+
|
376
|
+
expect_to_match_on_values(builder, valid_values) do |matcher|
|
377
|
+
matcher.with_message(/ is not included\Z/)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
371
381
|
it 'does not match when validation uses the default message instead of given message' do
|
372
382
|
builder = build_object_allowing(valid_values)
|
373
383
|
|
@@ -434,13 +444,25 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
434
444
|
shared_examples_for 'it supports in_array' do |args|
|
435
445
|
possible_values = args.fetch(:possible_values)
|
436
446
|
zero = args[:zero]
|
437
|
-
reserved_outside_value = args
|
447
|
+
reserved_outside_value = args[:reserved_outside_value]
|
438
448
|
|
439
449
|
define_method(:valid_values) { args.fetch(:possible_values) }
|
440
450
|
|
441
|
-
|
442
|
-
|
443
|
-
|
451
|
+
context 'when the record has no validations' do
|
452
|
+
it 'passes when used in the negative' do
|
453
|
+
builder = build_object
|
454
|
+
expect_not_to_match_on_values(builder, possible_values)
|
455
|
+
end
|
456
|
+
|
457
|
+
it 'fails when used in the positive with an appropriate failure message' do
|
458
|
+
builder = build_object
|
459
|
+
|
460
|
+
assertion = lambda do
|
461
|
+
expect_to_match_on_values(builder, possible_values)
|
462
|
+
end
|
463
|
+
|
464
|
+
expect(&assertion).to fail
|
465
|
+
end
|
444
466
|
end
|
445
467
|
|
446
468
|
it 'matches given the same array of valid values' do
|
@@ -466,12 +488,24 @@ describe Shoulda::Matchers::ActiveModel::ValidateInclusionOfMatcher, type: :mode
|
|
466
488
|
expect_not_to_match_on_values(builder, add_outside_value_to(possible_values))
|
467
489
|
end
|
468
490
|
|
469
|
-
|
470
|
-
|
471
|
-
|
491
|
+
if reserved_outside_value
|
492
|
+
it 'raises an error when valid and given value is our test outside value' do
|
493
|
+
error_class = Shoulda::Matchers::ActiveModel::CouldNotDetermineValueOutsideOfArray
|
494
|
+
builder = build_object_allowing([reserved_outside_value])
|
495
|
+
|
496
|
+
expect { expect_to_match_on_values(builder, [reserved_outside_value]) }.
|
497
|
+
to raise_error(error_class)
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'fails when used in the negative' do
|
502
|
+
builder = build_object_allowing(possible_values)
|
503
|
+
|
504
|
+
assertion = lambda do
|
505
|
+
expect_not_to_match_on_values(builder, possible_values)
|
506
|
+
end
|
472
507
|
|
473
|
-
expect
|
474
|
-
to raise_error(error_class)
|
508
|
+
expect(&assertion).to fail
|
475
509
|
end
|
476
510
|
|
477
511
|
it_behaves_like 'it supports allow_nil', valid_values: possible_values
|
@@ -33,8 +33,8 @@ describe Shoulda::Matchers::ActiveModel::ValidateLengthOfMatcher, type: :model d
|
|
33
33
|
attribute_name: :attr,
|
34
34
|
changing_values_with: :add_character,
|
35
35
|
expected_message: <<-MESSAGE.strip
|
36
|
-
Example
|
37
|
-
|
36
|
+
Expected Example to validate that the length of :attr is at least 4, but
|
37
|
+
this could not be proved.
|
38
38
|
After setting :attr to ‹"xxx"› -- which was read back as ‹"xxxa"› --
|
39
39
|
the matcher expected the Example to be invalid, but it was valid
|
40
40
|
instead.
|
@@ -56,6 +56,22 @@ Example did not properly validate that the length of :attr is at least
|
|
56
56
|
matcher.is_at_least(4)
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
it 'fails when used in the negative' do
|
61
|
+
assertion = lambda do
|
62
|
+
expect(validating_length(minimum: 4)).
|
63
|
+
not_to validate_length_of(:attr).is_at_least(4)
|
64
|
+
end
|
65
|
+
|
66
|
+
message = <<-MESSAGE
|
67
|
+
Expected Example not to validate that the length of :attr is at least 4,
|
68
|
+
but this could not be proved.
|
69
|
+
After setting :attr to ‹"xxxx"›, the matcher expected the Example to
|
70
|
+
be invalid, but it was valid instead.
|
71
|
+
MESSAGE
|
72
|
+
|
73
|
+
expect(&assertion).to fail_with_message(message)
|
74
|
+
end
|
59
75
|
end
|
60
76
|
|
61
77
|
context 'an attribute with a minimum length validation of 0' do
|
@@ -97,7 +113,8 @@ Example did not properly validate that the length of :attr is at least
|
|
97
113
|
attribute_name: :attr,
|
98
114
|
changing_values_with: :remove_character,
|
99
115
|
expected_message: <<-MESSAGE.strip
|
100
|
-
Example
|
116
|
+
Expected Example to validate that the length of :attr is at most 4, but
|
117
|
+
this could not be proved.
|
101
118
|
After setting :attr to ‹"xxxxx"› -- which was read back as ‹"xxxx"› --
|
102
119
|
the matcher expected the Example to be invalid, but it was valid
|
103
120
|
instead.
|
@@ -153,7 +170,8 @@ Example did not properly validate that the length of :attr is at most 4.
|
|
153
170
|
attribute_name: :attr,
|
154
171
|
changing_values_with: :add_character,
|
155
172
|
expected_message: <<-MESSAGE.strip
|
156
|
-
Example
|
173
|
+
Expected Example to validate that the length of :attr is 4, but this
|
174
|
+
could not be proved.
|
157
175
|
After setting :attr to ‹"xxx"› -- which was read back as ‹"xxxa"› --
|
158
176
|
the matcher expected the Example to be invalid, but it was valid
|
159
177
|
instead.
|
@@ -264,6 +282,35 @@ Example did not properly validate that the length of :attr is 4.
|
|
264
282
|
end
|
265
283
|
end
|
266
284
|
|
285
|
+
context 'qualified with allow_nil' do
|
286
|
+
context 'and validating with allow_nil' do
|
287
|
+
it 'accepts' do
|
288
|
+
expect(validating_length(minimum: 1, allow_nil: true)).
|
289
|
+
to validate_length_of(:attr).is_at_least(1).allow_nil
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context 'and not validating with allow_nil' do
|
294
|
+
it 'rejects' do
|
295
|
+
assertion = lambda do
|
296
|
+
expect(validating_length(minimum: 1)).
|
297
|
+
to validate_length_of(:attr).is_at_least(1).allow_nil
|
298
|
+
end
|
299
|
+
|
300
|
+
message = <<-MESSAGE
|
301
|
+
Expected Example to validate that the length of :attr is at least 1, but
|
302
|
+
this could not be proved.
|
303
|
+
After setting :attr to ‹nil›, the matcher expected the Example to be
|
304
|
+
valid, but it was invalid instead, producing these validation errors:
|
305
|
+
|
306
|
+
* attr: ["is too short (minimum is 1 character)"]
|
307
|
+
MESSAGE
|
308
|
+
|
309
|
+
expect(&assertion).to fail_with_message(message)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
267
314
|
def define_model_validating_length(options = {})
|
268
315
|
options = options.dup
|
269
316
|
attribute_name = options.delete(:attribute_name) { :attr }
|