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
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
4
|
+
describe Shoulda::Matchers::ActiveRecord::HaveSecureTokenMatcher,
|
5
|
+
type: :model do
|
6
|
+
|
7
|
+
if active_record_supports_has_secure_token?
|
8
|
+
describe '#description' do
|
9
|
+
it 'returns the message including the name of the default column' do
|
10
|
+
matcher = have_secure_token
|
11
|
+
expect(matcher.description).
|
12
|
+
to eq('have :token as a secure token')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns the message including the name of a provided column' do
|
16
|
+
matcher = have_secure_token(:special_token)
|
17
|
+
expect(matcher.description).
|
18
|
+
to eq('have :special_token as a secure token')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'matches when the subject configures has_secure_token with the db' do
|
23
|
+
create_table(:users) do |t|
|
24
|
+
t.string :token
|
25
|
+
t.index :token, unique: true
|
26
|
+
end
|
27
|
+
|
28
|
+
valid_model = define_model_class(:User) { has_secure_token }
|
29
|
+
|
30
|
+
expect(valid_model.new).to have_secure_token
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'matches when the subject configures has_secure_token with the db for ' \
|
34
|
+
'a custom attribute' do
|
35
|
+
create_table(:users) do |t|
|
36
|
+
t.string :auth_token
|
37
|
+
t.index :auth_token, unique: true
|
38
|
+
end
|
39
|
+
|
40
|
+
valid_model = define_model_class(:User) { has_secure_token(:auth_token) }
|
41
|
+
expect(valid_model.new).to have_secure_token(:auth_token)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'does not match when missing an token index' do
|
45
|
+
create_table(:users) do |t|
|
46
|
+
t.string :token
|
47
|
+
end
|
48
|
+
|
49
|
+
invalid_model = define_model_class(:User) { has_secure_token }
|
50
|
+
expected_message =
|
51
|
+
'Expected User to have :token as a secure token but the following ' \
|
52
|
+
'errors were found: missing unique index for users.token'
|
53
|
+
|
54
|
+
aggregate_failures do
|
55
|
+
expect(invalid_model.new).not_to have_secure_token
|
56
|
+
expect { expect(invalid_model.new).to have_secure_token }.
|
57
|
+
to fail_with_message(expected_message)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'does not match when missing a token column' do
|
62
|
+
create_table(:users)
|
63
|
+
invalid_model = define_model_class(:User) { has_secure_token }
|
64
|
+
|
65
|
+
expected_message =
|
66
|
+
'Expected User to have :token as a secure token but the following ' \
|
67
|
+
'errors were found: missing expected class and instance methods, ' \
|
68
|
+
'missing correct column token:string, missing unique index for ' \
|
69
|
+
'users.token'
|
70
|
+
|
71
|
+
aggregate_failures do
|
72
|
+
expect(invalid_model.new).not_to have_secure_token
|
73
|
+
expect { expect(invalid_model.new).to have_secure_token }.
|
74
|
+
to fail_with_message(expected_message)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'does not match when when lacking has_secure_token' do
|
79
|
+
create_table(:users) do |t|
|
80
|
+
t.string :token
|
81
|
+
t.index :token
|
82
|
+
end
|
83
|
+
|
84
|
+
invalid_model = define_model_class(:User)
|
85
|
+
|
86
|
+
expected_message =
|
87
|
+
'Expected User to have :token as a secure token but the following ' \
|
88
|
+
'errors were found: missing expected class and instance methods, ' \
|
89
|
+
'missing unique index for users.token'
|
90
|
+
|
91
|
+
aggregate_failures do
|
92
|
+
expect(invalid_model.new).not_to have_secure_token
|
93
|
+
expect { expect(invalid_model.new).to have_secure_token }.
|
94
|
+
to fail_with_message(expected_message)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'does not match when missing an index for a custom attribute' do
|
99
|
+
create_table(:users) do |t|
|
100
|
+
t.string :auth_token
|
101
|
+
end
|
102
|
+
|
103
|
+
invalid_model = define_model_class(:User) do
|
104
|
+
has_secure_token(:auth_token)
|
105
|
+
end
|
106
|
+
|
107
|
+
expected_message =
|
108
|
+
'Expected User to have :auth_token as a secure token but the ' \
|
109
|
+
'following errors were found: missing unique index for ' \
|
110
|
+
'users.auth_token'
|
111
|
+
|
112
|
+
aggregate_failures do
|
113
|
+
expect(invalid_model.new).not_to have_secure_token(:auth_token)
|
114
|
+
expect { expect(invalid_model.new).to have_secure_token(:auth_token) }.
|
115
|
+
to fail_with_message(expected_message)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'does not match when missing a column for a custom attribute' do
|
120
|
+
create_table(:users)
|
121
|
+
invalid_model = define_model_class(:User) do
|
122
|
+
has_secure_token(:auth_token)
|
123
|
+
end
|
124
|
+
|
125
|
+
expected_message =
|
126
|
+
'Expected User to have :auth_token as a secure token but the ' \
|
127
|
+
'following errors were found: missing expected class and instance ' \
|
128
|
+
'methods, missing correct column auth_token:string, missing unique ' \
|
129
|
+
'index for users.auth_token'
|
130
|
+
|
131
|
+
aggregate_failures do
|
132
|
+
expect(invalid_model.new).not_to have_secure_token(:auth_token)
|
133
|
+
expect { expect(invalid_model.new).to have_secure_token(:auth_token) }.
|
134
|
+
to fail_with_message(expected_message)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'does not match when when lacking has_secure_token for the attribute' do
|
139
|
+
create_table(:users) do |t|
|
140
|
+
t.string :auth_token
|
141
|
+
t.index :auth_token, unique: true
|
142
|
+
end
|
143
|
+
|
144
|
+
invalid_model = define_model_class(:User)
|
145
|
+
expected_message =
|
146
|
+
'Expected User to have :auth_token as a secure token but the ' \
|
147
|
+
'following errors were found: missing expected class and instance ' \
|
148
|
+
'methods'
|
149
|
+
|
150
|
+
aggregate_failures do
|
151
|
+
expect(invalid_model.new).not_to have_secure_token(:auth_token)
|
152
|
+
expect { expect(invalid_model.new).to have_secure_token(:auth_token) }.
|
153
|
+
to fail_with_message(expected_message)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'fails with the appropriate message when negated' do
|
158
|
+
create_table(:users) do |t|
|
159
|
+
t.string :token
|
160
|
+
t.index :token, unique: true
|
161
|
+
end
|
162
|
+
|
163
|
+
valid_model = define_model_class(:User) { has_secure_token }
|
164
|
+
|
165
|
+
expect { expect(valid_model.new).not_to have_secure_token }.
|
166
|
+
to fail_with_message('Did not expect User to have secure token :token')
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -82,8 +82,9 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
82
82
|
end
|
83
83
|
|
84
84
|
message = <<-MESSAGE
|
85
|
-
Example
|
86
|
-
within the scope of :scope1, :scope2, and :other
|
85
|
+
Expected Example to validate that :attr is case-sensitively unique
|
86
|
+
within the scope of :scope1, :scope2, and :other, but this could not be
|
87
|
+
proved.
|
87
88
|
Expected the validation to be scoped to :scope1, :scope2, and :other,
|
88
89
|
but it was scoped to :scope1 and :scope2 instead.
|
89
90
|
MESSAGE
|
@@ -108,8 +109,8 @@ within the scope of :scope1, :scope2, and :other.
|
|
108
109
|
end
|
109
110
|
|
110
111
|
message = <<-MESSAGE
|
111
|
-
Example
|
112
|
-
within the scope of :scope1.
|
112
|
+
Expected Example to validate that :attr is case-sensitively unique
|
113
|
+
within the scope of :scope1, but this could not be proved.
|
113
114
|
Expected the validation to be scoped to :scope1, but it was scoped to
|
114
115
|
:scope1 and :scope2 instead.
|
115
116
|
MESSAGE
|
@@ -131,8 +132,8 @@ within the scope of :scope1.
|
|
131
132
|
end
|
132
133
|
|
133
134
|
message = <<-MESSAGE
|
134
|
-
Example
|
135
|
-
within the scope of :scope.
|
135
|
+
Expected Example to validate that :attr is case-sensitively unique
|
136
|
+
within the scope of :scope, but this could not be proved.
|
136
137
|
Expected the validation to be scoped to :scope, but it was scoped to
|
137
138
|
:other instead.
|
138
139
|
MESSAGE
|
@@ -152,7 +153,8 @@ within the scope of :scope.
|
|
152
153
|
end
|
153
154
|
|
154
155
|
message = <<-MESSAGE
|
155
|
-
Example
|
156
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
157
|
+
this could not be proved.
|
156
158
|
Expected the validation not to be scoped to anything, but it was
|
157
159
|
scoped to :scope instead.
|
158
160
|
MESSAGE
|
@@ -171,7 +173,8 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
171
173
|
end
|
172
174
|
|
173
175
|
message = <<-MESSAGE
|
174
|
-
Example
|
176
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
177
|
+
this could not be proved.
|
175
178
|
Expected the validation not to be scoped to anything, but it was
|
176
179
|
scoped to :scope instead.
|
177
180
|
MESSAGE
|
@@ -193,8 +196,8 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
193
196
|
end
|
194
197
|
|
195
198
|
message = <<-MESSAGE.strip
|
196
|
-
Example
|
197
|
-
within the scope of :non_existent.
|
199
|
+
Expected Example to validate that :attr is case-sensitively unique
|
200
|
+
within the scope of :non_existent, but this could not be proved.
|
198
201
|
:non_existent does not seem to be an attribute on Example.
|
199
202
|
MESSAGE
|
200
203
|
|
@@ -216,8 +219,9 @@ within the scope of :non_existent.
|
|
216
219
|
end
|
217
220
|
|
218
221
|
message = <<-MESSAGE.strip
|
219
|
-
Example
|
220
|
-
within the scope of :non_existent1 and :non_existent2
|
222
|
+
Expected Example to validate that :attr is case-sensitively unique
|
223
|
+
within the scope of :non_existent1 and :non_existent2, but this could
|
224
|
+
not be proved.
|
221
225
|
:non_existent1 and :non_existent2 do not seem to be attributes on
|
222
226
|
Example.
|
223
227
|
MESSAGE
|
@@ -334,7 +338,8 @@ within the scope of :non_existent1 and :non_existent2.
|
|
334
338
|
end
|
335
339
|
|
336
340
|
message = <<-MESSAGE
|
337
|
-
Example
|
341
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
342
|
+
this could not be proved.
|
338
343
|
Given an existing Example whose :attr is ‹"value"›, after making a new
|
339
344
|
Example and setting its :attr to ‹"value"› as well, the matcher
|
340
345
|
expected the new Example to be invalid, but it was valid instead.
|
@@ -356,6 +361,17 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
356
361
|
end
|
357
362
|
end
|
358
363
|
|
364
|
+
context 'when the attribute is of integer type' do
|
365
|
+
it 'accepts' do
|
366
|
+
record = build_record_validating_uniqueness(
|
367
|
+
attribute_type: :integer,
|
368
|
+
attribute_options: { limit: 4 },
|
369
|
+
)
|
370
|
+
|
371
|
+
expect(record).to validate_uniqueness
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
359
375
|
context 'when the existing record was created beforehand' do
|
360
376
|
context 'when the subject is a new record' do
|
361
377
|
it 'accepts' do
|
@@ -518,8 +534,8 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
518
534
|
end
|
519
535
|
|
520
536
|
message = <<-MESSAGE
|
521
|
-
Example
|
522
|
-
within the scope of :other.
|
537
|
+
Expected Example to validate that :attr is case-sensitively unique
|
538
|
+
within the scope of :other, but this could not be proved.
|
523
539
|
Expected the validation to be scoped to :other, but it was not scoped
|
524
540
|
to anything.
|
525
541
|
MESSAGE
|
@@ -541,7 +557,8 @@ within the scope of :other.
|
|
541
557
|
end
|
542
558
|
|
543
559
|
message = <<-MESSAGE
|
544
|
-
Example
|
560
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
561
|
+
this could not be proved.
|
545
562
|
After taking the given Example, whose :attr is ‹"some value"›, and
|
546
563
|
saving it as the existing record, then making a new Example and
|
547
564
|
setting its :attr to ‹"some value"› as well, the matcher expected the
|
@@ -571,8 +588,9 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
571
588
|
end
|
572
589
|
|
573
590
|
message = <<-MESSAGE
|
574
|
-
Example
|
575
|
-
producing a custom validation error on failure
|
591
|
+
Expected Example to validate that :attr is case-sensitively unique,
|
592
|
+
producing a custom validation error on failure, but this could not be
|
593
|
+
proved.
|
576
594
|
After taking the given Example, whose :attr is ‹"some value"›, and
|
577
595
|
saving it as the existing record, then making a new Example and
|
578
596
|
setting its :attr to ‹"some value"› as well, the matcher expected the
|
@@ -614,8 +632,9 @@ producing a custom validation error on failure.
|
|
614
632
|
end
|
615
633
|
|
616
634
|
message = <<-MESSAGE
|
617
|
-
Example
|
618
|
-
producing a custom validation error on failure
|
635
|
+
Expected Example to validate that :attr is case-sensitively unique,
|
636
|
+
producing a custom validation error on failure, but this could not be
|
637
|
+
proved.
|
619
638
|
After taking the given Example, whose :attr is ‹"some value"›, and
|
620
639
|
saving it as the existing record, then making a new Example and
|
621
640
|
setting its :attr to ‹"some value"› as well, the matcher expected the
|
@@ -652,7 +671,8 @@ producing a custom validation error on failure.
|
|
652
671
|
default_value: 'some value',
|
653
672
|
changing_values_with: :next_value,
|
654
673
|
expected_message: <<-MESSAGE.strip
|
655
|
-
Example
|
674
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
675
|
+
this could not be proved.
|
656
676
|
After taking the given Example, whose :attr is ‹"some valuf"›, and
|
657
677
|
saving it as the existing record, then making a new Example and
|
658
678
|
setting its :attr to ‹"some valuf"› (read back as ‹"some valug"›) as
|
@@ -672,6 +692,28 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
672
692
|
}
|
673
693
|
}
|
674
694
|
)
|
695
|
+
|
696
|
+
it 'fails when used in the negative' do
|
697
|
+
assertion = lambda do
|
698
|
+
record = build_record_validating_uniqueness(
|
699
|
+
attribute_type: :string,
|
700
|
+
attribute_options: { limit: 1 }
|
701
|
+
)
|
702
|
+
|
703
|
+
expect(record).not_to validate_uniqueness
|
704
|
+
end
|
705
|
+
|
706
|
+
message = <<-MESSAGE
|
707
|
+
Expected Example not to validate that :attr is case-sensitively unique,
|
708
|
+
but this could not be proved.
|
709
|
+
After taking the given Example, setting its :attr to ‹"x"›, and saving
|
710
|
+
it as the existing record, then making a new Example and setting its
|
711
|
+
:attr to a different value, ‹"X"›, the matcher expected the new
|
712
|
+
Example to be invalid, but it was valid instead.
|
713
|
+
MESSAGE
|
714
|
+
|
715
|
+
expect(&assertion).to fail_with_message(message)
|
716
|
+
end
|
675
717
|
end
|
676
718
|
|
677
719
|
context 'when the model has a scoped uniqueness validation' do
|
@@ -721,60 +763,59 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
721
763
|
include_context 'it supports scoped attributes of a certain type',
|
722
764
|
column_type: :integer
|
723
765
|
|
724
|
-
|
725
|
-
|
726
|
-
|
766
|
+
context 'when one of the scoped attributes is an enum' do
|
767
|
+
it 'accepts' do
|
768
|
+
record = build_record_validating_scoped_uniqueness_with_enum(
|
769
|
+
enum_scope: :scope
|
770
|
+
)
|
771
|
+
expect(record).to validate_uniqueness.scoped_to(:scope)
|
772
|
+
end
|
773
|
+
|
774
|
+
context 'when too narrow of a scope is specified' do
|
775
|
+
it 'rejects with an appropriate failure message' do
|
727
776
|
record = build_record_validating_scoped_uniqueness_with_enum(
|
728
|
-
enum_scope: :
|
777
|
+
enum_scope: :scope1,
|
778
|
+
additional_scopes: [:scope2],
|
779
|
+
additional_attributes: [:other]
|
729
780
|
)
|
730
|
-
expect(record).to validate_uniqueness.scoped_to(:scope)
|
731
|
-
end
|
732
781
|
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
additional_attributes: [:other]
|
739
|
-
)
|
740
|
-
|
741
|
-
assertion = lambda do
|
742
|
-
expect(record).
|
743
|
-
to validate_uniqueness.
|
744
|
-
scoped_to(:scope1, :scope2, :other)
|
745
|
-
end
|
782
|
+
assertion = lambda do
|
783
|
+
expect(record).
|
784
|
+
to validate_uniqueness.
|
785
|
+
scoped_to(:scope1, :scope2, :other)
|
786
|
+
end
|
746
787
|
|
747
|
-
|
748
|
-
Example
|
749
|
-
within the scope of :scope1, :scope2, and :other
|
788
|
+
message = <<-MESSAGE
|
789
|
+
Expected Example to validate that :attr is case-sensitively unique
|
790
|
+
within the scope of :scope1, :scope2, and :other, but this could not be
|
791
|
+
proved.
|
750
792
|
Expected the validation to be scoped to :scope1, :scope2, and :other,
|
751
793
|
but it was scoped to :scope1 and :scope2 instead.
|
752
|
-
|
794
|
+
MESSAGE
|
753
795
|
|
754
|
-
|
755
|
-
end
|
796
|
+
expect(&assertion).to fail_with_message(message)
|
756
797
|
end
|
798
|
+
end
|
757
799
|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
800
|
+
context 'when too broad of a scope is specified' do
|
801
|
+
it 'rejects with an appropriate failure message' do
|
802
|
+
record = build_record_validating_scoped_uniqueness_with_enum(
|
803
|
+
enum_scope: :scope1,
|
804
|
+
additional_scopes: [:scope2]
|
805
|
+
)
|
764
806
|
|
765
|
-
|
766
|
-
|
767
|
-
|
807
|
+
assertion = lambda do
|
808
|
+
expect(record).to validate_uniqueness.scoped_to(:scope1)
|
809
|
+
end
|
768
810
|
|
769
|
-
|
770
|
-
Example
|
771
|
-
within the scope of :scope1.
|
811
|
+
message = <<-MESSAGE
|
812
|
+
Expected Example to validate that :attr is case-sensitively unique
|
813
|
+
within the scope of :scope1, but this could not be proved.
|
772
814
|
Expected the validation to be scoped to :scope1, but it was scoped to
|
773
815
|
:scope1 and :scope2 instead.
|
774
|
-
|
816
|
+
MESSAGE
|
775
817
|
|
776
|
-
|
777
|
-
end
|
818
|
+
expect(&assertion).to fail_with_message(message)
|
778
819
|
end
|
779
820
|
end
|
780
821
|
end
|
@@ -808,7 +849,11 @@ within the scope of :scope1.
|
|
808
849
|
end
|
809
850
|
end
|
810
851
|
|
811
|
-
if
|
852
|
+
if (
|
853
|
+
database_supports_array_columns? &&
|
854
|
+
active_record_supports_array_columns? &&
|
855
|
+
active_record_uniqueness_supports_array_columns?
|
856
|
+
)
|
812
857
|
context 'when one of the scoped attributes is a array-of-string column' do
|
813
858
|
include_examples 'it supports scoped attributes of a certain type',
|
814
859
|
column_type: :string,
|
@@ -898,8 +943,8 @@ within the scope of :scope1.
|
|
898
943
|
end
|
899
944
|
|
900
945
|
message = <<-MESSAGE
|
901
|
-
Example
|
902
|
-
|
946
|
+
Expected Example to validate that :attr is case-insensitively unique,
|
947
|
+
but this could not be proved.
|
903
948
|
After taking the given Example, whose :attr is ‹"some value"›, and
|
904
949
|
saving it as the existing record, then making a new Example and
|
905
950
|
setting its :attr to a different value, ‹"SOME VALUE"›, the matcher
|
@@ -924,12 +969,13 @@ unique.
|
|
924
969
|
end
|
925
970
|
|
926
971
|
message = <<-MESSAGE
|
927
|
-
Example
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
972
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
973
|
+
this could not be proved.
|
974
|
+
After taking the given Example, setting its :attr to ‹"dummy value"›,
|
975
|
+
and saving it as the existing record, then making a new Example and
|
976
|
+
setting its :attr to a different value, ‹"DUMMY VALUE"›, the matcher
|
977
|
+
expected the new Example to be valid, but it was invalid instead,
|
978
|
+
producing these validation errors:
|
933
979
|
|
934
980
|
* attr: ["has already been taken"]
|
935
981
|
MESSAGE
|
@@ -957,8 +1003,8 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
957
1003
|
default_value: 'some value',
|
958
1004
|
changing_values_with: :next_value,
|
959
1005
|
expected_message: <<-MESSAGE.strip
|
960
|
-
Example
|
961
|
-
|
1006
|
+
Expected Example to validate that :attr is case-insensitively unique,
|
1007
|
+
but this could not be proved.
|
962
1008
|
After taking the given Example, whose :attr is ‹"some valuf"›, and
|
963
1009
|
saving it as the existing record, then making a new Example and
|
964
1010
|
setting its :attr to ‹"some valuf"› (read back as ‹"some valug"›) as
|
@@ -1038,8 +1084,8 @@ unique.
|
|
1038
1084
|
end
|
1039
1085
|
|
1040
1086
|
message = <<-MESSAGE
|
1041
|
-
Example
|
1042
|
-
|
1087
|
+
Expected Example to validate that :attr is case-sensitively unique as
|
1088
|
+
long as it is not nil, but this could not be proved.
|
1043
1089
|
After taking the given Example, setting its :attr to ‹nil›, and saving
|
1044
1090
|
it as the existing record, then making a new Example and setting its
|
1045
1091
|
:attr to ‹nil› as well, the matcher expected the new Example to be
|
@@ -1062,8 +1108,8 @@ but only if it is not nil.
|
|
1062
1108
|
end
|
1063
1109
|
|
1064
1110
|
message = <<-MESSAGE
|
1065
|
-
Example
|
1066
|
-
|
1111
|
+
Expected Example to validate that :attr is case-sensitively unique as
|
1112
|
+
long as it is not nil, but this could not be proved.
|
1067
1113
|
Given an existing Example, after setting its :attr to ‹nil›, then
|
1068
1114
|
making a new Example and setting its :attr to ‹nil› as well, the
|
1069
1115
|
matcher expected the new Example to be valid, but it was invalid
|
@@ -1167,8 +1213,8 @@ but only if it is not nil.
|
|
1167
1213
|
end
|
1168
1214
|
|
1169
1215
|
message = <<-MESSAGE
|
1170
|
-
Example
|
1171
|
-
|
1216
|
+
Expected Example to validate that :attr is case-sensitively unique as
|
1217
|
+
long as it is not blank, but this could not be proved.
|
1172
1218
|
After taking the given Example, setting its :attr to ‹""›, and saving
|
1173
1219
|
it as the existing record, then making a new Example and setting its
|
1174
1220
|
:attr to ‹""› as well, the matcher expected the new Example to be
|
@@ -1191,8 +1237,8 @@ but only if it is not blank.
|
|
1191
1237
|
end
|
1192
1238
|
|
1193
1239
|
message = <<-MESSAGE
|
1194
|
-
Example
|
1195
|
-
|
1240
|
+
Expected Example to validate that :attr is case-sensitively unique as
|
1241
|
+
long as it is not blank, but this could not be proved.
|
1196
1242
|
Given an existing Example, after setting its :attr to ‹""›, then
|
1197
1243
|
making a new Example and setting its :attr to ‹""› as well, the
|
1198
1244
|
matcher expected the new Example to be valid, but it was invalid
|
@@ -1217,8 +1263,8 @@ but only if it is not blank.
|
|
1217
1263
|
end
|
1218
1264
|
|
1219
1265
|
message = <<-MESSAGE
|
1220
|
-
Example
|
1221
|
-
|
1266
|
+
Expected Example to validate that :attr is case-sensitively unique as
|
1267
|
+
long as it is not blank, but this could not be proved.
|
1222
1268
|
After taking the given Example, setting its :attr to ‹""›, and saving
|
1223
1269
|
it as the existing record, then making a new Example and setting its
|
1224
1270
|
:attr to ‹""› as well, the matcher expected the new Example to be
|
@@ -1243,8 +1289,8 @@ but only if it is not blank.
|
|
1243
1289
|
end
|
1244
1290
|
|
1245
1291
|
message = <<-MESSAGE
|
1246
|
-
Example
|
1247
|
-
|
1292
|
+
Expected Example to validate that :attr is case-sensitively unique as
|
1293
|
+
long as it is not blank, but this could not be proved.
|
1248
1294
|
Given an existing Example, after setting its :attr to ‹""›, then
|
1249
1295
|
making a new Example and setting its :attr to ‹""› as well, the
|
1250
1296
|
matcher expected the new Example to be valid, but it was invalid
|
@@ -1266,7 +1312,10 @@ but only if it is not blank.
|
|
1266
1312
|
favoriteable_type: { type: :string, options: { null: false } }
|
1267
1313
|
}
|
1268
1314
|
favorite_model = define_model 'Favorite', favorite_columns do
|
1269
|
-
|
1315
|
+
if respond_to?(:attr_accessible)
|
1316
|
+
attr_accessible :favoriteable
|
1317
|
+
end
|
1318
|
+
|
1270
1319
|
belongs_to :favoriteable, polymorphic: true
|
1271
1320
|
validates :favoriteable, presence: true
|
1272
1321
|
validates :favoriteable_id, uniqueness: { scope: :favoriteable_type }
|
@@ -1291,7 +1340,10 @@ but only if it is not blank.
|
|
1291
1340
|
favoriteable_type: { type: :string, options: { null: false } }
|
1292
1341
|
}
|
1293
1342
|
favorite_model = define_model 'Models::Favorite', favorite_columns do
|
1294
|
-
|
1343
|
+
if respond_to?(:attr_accessible)
|
1344
|
+
attr_accessible :favoriteable
|
1345
|
+
end
|
1346
|
+
|
1295
1347
|
belongs_to :favoriteable, polymorphic: true
|
1296
1348
|
validates :favoriteable, presence: true
|
1297
1349
|
validates :favoriteable_id, uniqueness: { scope: :favoriteable_type }
|
@@ -1317,7 +1369,8 @@ but only if it is not blank.
|
|
1317
1369
|
end
|
1318
1370
|
|
1319
1371
|
message = <<-MESSAGE.strip
|
1320
|
-
Example
|
1372
|
+
Expected Example to validate that :attr is case-sensitively unique, but
|
1373
|
+
this could not be proved.
|
1321
1374
|
:attr does not seem to be an attribute on Example.
|
1322
1375
|
MESSAGE
|
1323
1376
|
|
@@ -1344,13 +1397,14 @@ Example did not properly validate that :attr is case-sensitively unique.
|
|
1344
1397
|
end
|
1345
1398
|
|
1346
1399
|
message = <<-MESSAGE.strip
|
1347
|
-
Example
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
instead, producing these
|
1400
|
+
Expected Example to validate that :name is case-sensitively unique, but
|
1401
|
+
this could not be proved.
|
1402
|
+
After taking the given Example, setting its :name to ‹"dummy value"›
|
1403
|
+
(read back as ‹"DUMMY VALUE"›), and saving it as the existing record,
|
1404
|
+
then making a new Example and setting its :name to ‹"dummy value"›
|
1405
|
+
(read back as ‹"DUMMY VALUE"›) as well, the matcher expected the new
|
1406
|
+
Example to be valid, but it was invalid instead, producing these
|
1407
|
+
validation errors:
|
1354
1408
|
|
1355
1409
|
* name: ["has already been taken"]
|
1356
1410
|
|
@@ -1409,6 +1463,18 @@ Example did not properly validate that :name is case-sensitively unique.
|
|
1409
1463
|
end
|
1410
1464
|
end
|
1411
1465
|
|
1466
|
+
context 'when the column is a boolean column' do
|
1467
|
+
it 'accepts (and does not print a warning)' do
|
1468
|
+
record = build_record_validating_uniqueness(attribute_type: :boolean)
|
1469
|
+
running_validation = -> { expect(record).to validate_uniqueness }
|
1470
|
+
message =
|
1471
|
+
'You attempted to assign a value which is not explicitly `true` or ' +
|
1472
|
+
'`false`'
|
1473
|
+
|
1474
|
+
expect(&running_validation).not_to print_warning_including(message)
|
1475
|
+
end
|
1476
|
+
end
|
1477
|
+
|
1412
1478
|
let(:model_attributes) { {} }
|
1413
1479
|
|
1414
1480
|
def default_attribute
|
@@ -1547,8 +1613,10 @@ Example did not properly validate that :name is case-sensitively unique.
|
|
1547
1613
|
m.validates_uniqueness_of attribute_name,
|
1548
1614
|
validation_options.merge(scope: scope_attribute_names)
|
1549
1615
|
|
1550
|
-
|
1551
|
-
|
1616
|
+
if m.respond_to?(:attr_accessible)
|
1617
|
+
attributes.each do |attr|
|
1618
|
+
m.attr_accessible(attr[:name])
|
1619
|
+
end
|
1552
1620
|
end
|
1553
1621
|
|
1554
1622
|
block.call(m) if block
|
@@ -1591,7 +1659,9 @@ Example did not properly validate that :name is case-sensitively unique.
|
|
1591
1659
|
|
1592
1660
|
def define_model_without_validation
|
1593
1661
|
define_model(:example, attribute_name => :string) do |model|
|
1594
|
-
model.attr_accessible
|
1662
|
+
if model.respond_to?(:attr_accessible)
|
1663
|
+
model.attr_accessible(attribute_name)
|
1664
|
+
end
|
1595
1665
|
end
|
1596
1666
|
end
|
1597
1667
|
|