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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.hound/ruby.yml +336 -316
  3. data/.python-version +1 -0
  4. data/.rubocop.yml +3 -1
  5. data/.travis.yml +7 -6
  6. data/Appraisals +76 -44
  7. data/CONTRIBUTING.md +137 -66
  8. data/Gemfile +5 -5
  9. data/Gemfile.lock +30 -35
  10. data/MAINTAINING.md +250 -0
  11. data/MIT-LICENSE +1 -1
  12. data/NEWS.md +176 -4
  13. data/README.md +138 -200
  14. data/Rakefile +7 -0
  15. data/bin/setup +190 -0
  16. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +4 -0
  17. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -6
  18. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -17
  19. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +27 -0
  20. data/gemfiles/4.2.gemfile +21 -20
  21. data/gemfiles/4.2.gemfile.lock +143 -140
  22. data/gemfiles/5.0.gemfile +37 -0
  23. data/gemfiles/5.0.gemfile.lock +238 -0
  24. data/gemfiles/5.1.gemfile +38 -0
  25. data/gemfiles/5.1.gemfile.lock +254 -0
  26. data/gemfiles/5.2.gemfile +40 -0
  27. data/gemfiles/5.2.gemfile.lock +273 -0
  28. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +18 -6
  29. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -1
  30. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  31. data/lib/shoulda/matchers/action_controller/route_matcher.rb +87 -27
  32. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +1 -0
  33. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +0 -4
  34. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +5 -0
  35. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -0
  36. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +26 -11
  37. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +39 -4
  38. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +116 -47
  39. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +127 -38
  40. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +55 -37
  41. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +30 -1
  42. data/lib/shoulda/matchers/active_model/validation_matcher.rb +11 -4
  43. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +11 -6
  44. data/lib/shoulda/matchers/active_record.rb +3 -0
  45. data/lib/shoulda/matchers/active_record/association_matcher.rb +172 -22
  46. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
  47. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +11 -6
  48. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +46 -0
  49. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +51 -0
  50. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +268 -38
  51. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  52. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +111 -0
  53. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +207 -79
  54. data/lib/shoulda/matchers/doublespeak/object_double.rb +5 -1
  55. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +100 -21
  56. data/lib/shoulda/matchers/rails_shim.rb +133 -52
  57. data/lib/shoulda/matchers/routing.rb +2 -2
  58. data/lib/shoulda/matchers/util.rb +23 -1
  59. data/lib/shoulda/matchers/util/word_wrap.rb +6 -2
  60. data/lib/shoulda/matchers/version.rb +1 -1
  61. data/script/install_gems_in_all_appraisals +3 -1
  62. data/script/run_all_tests +3 -1
  63. data/script/supported_ruby_versions +7 -0
  64. data/script/update_gem_in_all_appraisals +3 -1
  65. data/script/update_gems_in_all_appraisals +3 -1
  66. data/shoulda-matchers.gemspec +3 -3
  67. data/spec/acceptance/independent_matchers_spec.rb +2 -2
  68. data/spec/acceptance/multiple_libraries_integration_spec.rb +1 -1
  69. data/spec/acceptance/rails_integration_spec.rb +2 -2
  70. data/spec/spec_helper.rb +2 -3
  71. data/spec/support/acceptance/helpers.rb +2 -0
  72. data/spec/support/acceptance/helpers/command_helpers.rb +17 -4
  73. data/spec/support/acceptance/helpers/rails_migration_helpers.rb +21 -0
  74. data/spec/support/acceptance/helpers/step_helpers.rb +1 -1
  75. data/spec/support/tests/current_bundle.rb +3 -9
  76. data/spec/support/tests/filesystem.rb +2 -2
  77. data/spec/support/unit/attribute.rb +0 -2
  78. data/spec/support/unit/capture.rb +9 -3
  79. data/spec/support/unit/helpers/action_pack_versions.rb +22 -0
  80. data/spec/support/unit/helpers/active_model_versions.rb +4 -0
  81. data/spec/support/unit/helpers/active_record_versions.rb +22 -2
  82. data/spec/support/unit/helpers/active_resource_builder.rb +2 -2
  83. data/spec/support/unit/helpers/controller_builder.rb +1 -1
  84. data/spec/support/unit/helpers/message_helpers.rb +19 -0
  85. data/spec/support/unit/helpers/rails_versions.rb +14 -0
  86. data/spec/support/unit/matchers/fail_with_message_matcher.rb +7 -5
  87. data/spec/support/unit/matchers/print_warning_including.rb +21 -13
  88. data/spec/support/unit/model_creation_strategies/active_record.rb +1 -1
  89. data/spec/support/unit/model_creators/active_record.rb +0 -1
  90. data/spec/support/unit/model_creators/basic.rb +7 -2
  91. data/spec/support/unit/rails_application.rb +25 -0
  92. data/spec/support/unit/record_validating_confirmation_builder.rb +5 -2
  93. data/spec/support/unit/validation_matcher_scenario.rb +0 -2
  94. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +18 -18
  95. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +33 -5
  96. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +1 -1
  97. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +80 -78
  98. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +7 -9
  99. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +28 -4
  100. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +19 -1
  101. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +27 -4
  102. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +62 -5
  103. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +52 -18
  104. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +51 -4
  105. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +99 -71
  106. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +41 -15
  107. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +445 -15
  108. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +615 -93
  109. data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +169 -0
  110. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +167 -97
  111. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +2 -4
  112. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +152 -19
  113. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +258 -94
  114. data/spec/unit_spec_helper.rb +9 -1
  115. data/zeus.json +1 -1
  116. metadata +31 -16
  117. data/gemfiles/4.0.0.gemfile +0 -38
  118. data/gemfiles/4.0.0.gemfile.lock +0 -223
  119. data/gemfiles/4.0.1.gemfile +0 -38
  120. data/gemfiles/4.0.1.gemfile.lock +0 -225
  121. data/gemfiles/4.1.gemfile +0 -38
  122. data/gemfiles/4.1.gemfile.lock +0 -220
  123. 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 did not properly validate that :attr is case-sensitively unique
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 did not properly validate that :attr is case-sensitively unique
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 did not properly validate that :attr is case-sensitively unique
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 did not properly validate that :attr is case-sensitively unique.
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 did not properly validate that :attr is case-sensitively unique.
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 did not properly validate that :attr is case-sensitively unique
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 did not properly validate that :attr is case-sensitively unique
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 did not properly validate that :attr is case-sensitively unique.
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 did not properly validate that :attr is case-sensitively unique
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 did not properly validate that :attr is case-sensitively unique.
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 did not properly validate that :attr is case-sensitively unique,
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 did not properly validate that :attr is case-sensitively unique,
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 did not properly validate that :attr is case-sensitively unique.
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
- if active_record_supports_enum?
725
- context 'when one of the scoped attributes is an enum' do
726
- it 'accepts' do
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: :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
- context 'when too narrow of a scope is specified' do
734
- it 'rejects with an appropriate failure message' do
735
- record = build_record_validating_scoped_uniqueness_with_enum(
736
- enum_scope: :scope1,
737
- additional_scopes: [:scope2],
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
- message = <<-MESSAGE
748
- Example did not properly validate that :attr is case-sensitively unique
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
- MESSAGE
794
+ MESSAGE
753
795
 
754
- expect(&assertion).to fail_with_message(message)
755
- end
796
+ expect(&assertion).to fail_with_message(message)
756
797
  end
798
+ end
757
799
 
758
- context 'when too broad of a scope is specified' do
759
- it 'rejects with an appropriate failure message' do
760
- record = build_record_validating_scoped_uniqueness_with_enum(
761
- enum_scope: :scope1,
762
- additional_scopes: [:scope2]
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
- assertion = lambda do
766
- expect(record).to validate_uniqueness.scoped_to(:scope1)
767
- end
807
+ assertion = lambda do
808
+ expect(record).to validate_uniqueness.scoped_to(:scope1)
809
+ end
768
810
 
769
- message = <<-MESSAGE
770
- Example did not properly validate that :attr is case-sensitively unique
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
- MESSAGE
816
+ MESSAGE
775
817
 
776
- expect(&assertion).to fail_with_message(message)
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 database_supports_array_columns? && active_record_supports_array_columns?
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 did not properly validate that :attr is case-insensitively
902
- unique.
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 did not properly validate that :attr is case-sensitively unique.
928
- After taking the given Example, setting its :attr to ‹"an arbitrary
929
- value"›, and saving it as the existing record, then making a new
930
- Example and setting its :attr to a different value, ‹"AN ARBITRARY
931
- VALUE"›, the matcher expected the new Example to be valid, but it was
932
- invalid instead, producing these validation errors:
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 did not properly validate that :attr is case-insensitively
961
- unique.
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 did not properly validate that :attr is case-sensitively unique,
1042
- but only if it is not nil.
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 did not properly validate that :attr is case-sensitively unique,
1066
- but only if it is not nil.
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 did not properly validate that :attr is case-sensitively unique,
1171
- but only if it is not blank.
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 did not properly validate that :attr is case-sensitively unique,
1195
- but only if it is not blank.
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 did not properly validate that :attr is case-sensitively unique,
1221
- but only if it is not blank.
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 did not properly validate that :attr is case-sensitively unique,
1247
- but only if it is not blank.
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
- attr_accessible :favoriteable
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
- attr_accessible :favoriteable
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 did not properly validate that :attr is case-sensitively unique.
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 did not properly validate that :name is case-sensitively unique.
1348
- After taking the given Example, setting its :name to ‹"an arbitrary
1349
- value"› (read back as ‹"AN ARBITRARY VALUE"›), and saving it as the
1350
- existing record, then making a new Example and setting its :name to
1351
- ‹"an arbitrary value"› (read back as ‹"AN ARBITRARY VALUE"›) as well,
1352
- the matcher expected the new Example to be valid, but it was invalid
1353
- instead, producing these validation errors:
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
- attributes.each do |attr|
1551
- m.attr_accessible(attr[:name])
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(attribute_name)
1662
+ if model.respond_to?(:attr_accessible)
1663
+ model.attr_accessible(attribute_name)
1664
+ end
1595
1665
  end
1596
1666
  end
1597
1667