shoulda-matchers 2.8.0 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/.hound_config/ruby.yml +7 -0
  3. data/.travis.yml +11 -54
  4. data/Appraisals +45 -100
  5. data/CONTRIBUTING.md +51 -7
  6. data/Gemfile +7 -19
  7. data/Gemfile.lock +60 -134
  8. data/Guardfile +5 -0
  9. data/NEWS.md +203 -0
  10. data/README.md +95 -50
  11. data/Rakefile +1 -0
  12. data/doc_config/yard/templates/default/layout/html/setup.rb +1 -1
  13. data/gemfiles/4.0.0.gemfile +10 -7
  14. data/gemfiles/4.0.0.gemfile.lock +103 -79
  15. data/gemfiles/4.0.1.gemfile +10 -7
  16. data/gemfiles/4.0.1.gemfile.lock +109 -83
  17. data/gemfiles/4.1.gemfile +10 -7
  18. data/gemfiles/4.1.gemfile.lock +109 -85
  19. data/gemfiles/4.2.gemfile +10 -9
  20. data/gemfiles/4.2.gemfile.lock +86 -78
  21. data/lib/shoulda/matchers.rb +13 -18
  22. data/lib/shoulda/matchers/action_controller.rb +4 -1
  23. data/lib/shoulda/matchers/action_controller/flash_store.rb +95 -0
  24. data/lib/shoulda/matchers/action_controller/{strong_parameters_matcher.rb → permit_matcher.rb} +147 -30
  25. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  26. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -1
  27. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +1 -1
  28. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -1
  29. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -1
  30. data/lib/shoulda/matchers/action_controller/route_params.rb +15 -6
  31. data/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  32. data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +30 -136
  33. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +28 -109
  34. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +103 -0
  35. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +1 -12
  36. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +79 -10
  37. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +10 -0
  38. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +21 -0
  39. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +24 -0
  40. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -5
  41. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +29 -10
  42. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +27 -10
  43. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +27 -12
  44. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +56 -20
  45. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +3 -11
  46. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +65 -0
  47. data/lib/shoulda/matchers/active_record/association_matcher.rb +40 -6
  48. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +21 -7
  49. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +11 -40
  50. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +1 -1
  51. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +2 -6
  52. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +137 -22
  53. data/lib/shoulda/matchers/configuration.rb +20 -0
  54. data/lib/shoulda/matchers/doublespeak.rb +11 -1
  55. data/lib/shoulda/matchers/doublespeak/double.rb +29 -11
  56. data/lib/shoulda/matchers/doublespeak/double_collection.rb +4 -3
  57. data/lib/shoulda/matchers/doublespeak/method_call.rb +35 -0
  58. data/lib/shoulda/matchers/doublespeak/object_double.rb +7 -2
  59. data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +4 -3
  60. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +3 -3
  61. data/lib/shoulda/matchers/doublespeak/world.rb +21 -1
  62. data/lib/shoulda/matchers/integrations.rb +43 -0
  63. data/lib/shoulda/matchers/integrations/configuration.rb +68 -0
  64. data/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  65. data/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  66. data/lib/shoulda/matchers/integrations/libraries.rb +15 -0
  67. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +31 -0
  68. data/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  69. data/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  70. data/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  71. data/lib/shoulda/matchers/integrations/libraries/rails.rb +30 -0
  72. data/lib/shoulda/matchers/integrations/rails.rb +12 -0
  73. data/lib/shoulda/matchers/integrations/registry.rb +28 -0
  74. data/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  75. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  76. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  77. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  78. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  79. data/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  80. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  81. data/lib/shoulda/matchers/rails_shim.rb +0 -40
  82. data/lib/shoulda/matchers/version.rb +1 -1
  83. data/script/SUPPORTED_VERSIONS +1 -1
  84. data/script/update_gems_in_all_appraisals +14 -0
  85. data/shoulda-matchers.gemspec +2 -2
  86. data/spec/acceptance/active_model_integration_spec.rb +4 -1
  87. data/spec/acceptance/independent_matchers_spec.rb +6 -6
  88. data/spec/acceptance/multiple_libraries_integration_spec.rb +52 -0
  89. data/spec/acceptance/rails_integration_spec.rb +15 -5
  90. data/spec/acceptance_spec_helper.rb +8 -0
  91. data/spec/doublespeak_spec_helper.rb +14 -0
  92. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +110 -0
  93. data/spec/support/acceptance/helpers.rb +2 -0
  94. data/spec/support/acceptance/helpers/base_helpers.rb +6 -1
  95. data/spec/support/acceptance/helpers/command_helpers.rb +6 -2
  96. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -8
  97. data/spec/support/acceptance/helpers/n_unit_helpers.rb +25 -0
  98. data/spec/support/acceptance/helpers/rspec_helpers.rb +2 -0
  99. data/spec/support/acceptance/helpers/step_helpers.rb +13 -19
  100. data/spec/support/acceptance/matchers/have_output.rb +1 -1
  101. data/spec/support/tests/bundle.rb +1 -1
  102. data/spec/support/tests/command_runner.rb +25 -13
  103. data/spec/support/tests/current_bundle.rb +47 -0
  104. data/spec/support/tests/database.rb +28 -0
  105. data/spec/support/tests/database_adapters/postgresql.rb +25 -0
  106. data/spec/support/tests/database_adapters/sqlite3.rb +26 -0
  107. data/spec/support/tests/database_configuration.rb +33 -0
  108. data/spec/support/tests/database_configuration_registry.rb +28 -0
  109. data/spec/support/tests/filesystem.rb +25 -2
  110. data/spec/support/unit/helpers/active_record_versions.rb +12 -0
  111. data/spec/support/unit/helpers/class_builder.rb +6 -2
  112. data/spec/support/unit/helpers/column_type_helpers.rb +26 -0
  113. data/spec/support/unit/helpers/controller_builder.rb +0 -28
  114. data/spec/support/unit/helpers/database_helpers.rb +18 -0
  115. data/spec/support/unit/helpers/model_builder.rb +38 -6
  116. data/spec/support/unit/helpers/rails_versions.rb +2 -2
  117. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +9 -8
  118. data/spec/support/unit/matchers/fail_with_message_matcher.rb +1 -1
  119. data/spec/support/unit/rails_application.rb +29 -13
  120. data/spec/support/unit/record_validating_confirmation_builder.rb +1 -2
  121. data/spec/support/unit/shared_examples/set_session_or_flash.rb +355 -0
  122. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +433 -0
  123. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +1 -5
  124. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +37 -0
  125. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +23 -147
  126. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +8 -285
  127. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +562 -0
  128. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +81 -14
  129. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +16 -8
  130. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +101 -9
  131. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +39 -1
  132. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +39 -1
  133. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +39 -0
  134. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -17
  135. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -17
  136. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -17
  137. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +838 -271
  138. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -19
  139. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +93 -0
  140. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +3 -3
  141. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +25 -0
  142. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +905 -0
  143. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +17 -11
  144. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +1 -1
  145. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +144 -43
  146. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +1 -1
  147. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +36 -11
  148. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +29 -16
  149. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +8 -5
  150. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +1 -1
  151. data/spec/unit_spec_helper.rb +15 -14
  152. data/spec/warnings_spy.rb +1 -1
  153. metadata +68 -29
  154. data/docs.watchr +0 -5
  155. data/gemfiles/3.0.gemfile +0 -26
  156. data/gemfiles/3.0.gemfile.lock +0 -173
  157. data/gemfiles/3.1.gemfile +0 -32
  158. data/gemfiles/3.1.gemfile.lock +0 -212
  159. data/gemfiles/3.1_1.9.2.gemfile +0 -32
  160. data/gemfiles/3.1_1.9.2.gemfile.lock +0 -212
  161. data/gemfiles/3.2.gemfile +0 -33
  162. data/gemfiles/3.2.gemfile.lock +0 -212
  163. data/gemfiles/3.2_1.9.2.gemfile +0 -31
  164. data/gemfiles/3.2_1.9.2.gemfile.lock +0 -207
  165. data/lib/shoulda/matchers/assertion_error.rb +0 -27
  166. data/lib/shoulda/matchers/doublespeak/structs.rb +0 -10
  167. data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +0 -39
  168. data/lib/shoulda/matchers/integrations/rspec.rb +0 -19
  169. data/lib/shoulda/matchers/integrations/test_unit.rb +0 -34
  170. data/spec/unit/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +0 -331
  171. data/spec/unit/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -564
@@ -1,5 +1,13 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
+ describe Shoulda::Matchers::ActiveModel do
4
+ describe '#allow_values' do
5
+ it 'is aliased to #allow_value' do
6
+ expect(method(:allow_values)).to eq(method(:allow_value))
7
+ end
8
+ end
9
+ end
10
+
3
11
  describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
4
12
  context "#description" do
5
13
  it 'describes itself with multiple values' do
@@ -165,24 +173,29 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
165
173
  less_than_or_equal_to: 50000
166
174
  end.new
167
175
  end
176
+
168
177
  bad_values = [nil, '', 'abc', '0', '50001', '123456', []]
169
178
 
170
- it 'allows a good value' do
179
+ it 'matches given a good value' do
171
180
  expect(model).to allow_value('12345').for(:attr)
172
181
  end
173
182
 
174
- bad_values.each do |bad_value|
175
- it "rejects a bad value (#{bad_value.inspect})" do
183
+ it 'does not match given a bad value' do
184
+ bad_values.each do |bad_value|
176
185
  expect(model).not_to allow_value(bad_value).for(:attr)
177
186
  end
178
187
  end
179
188
 
180
- it "rejects several bad values (#{bad_values.map(&:inspect).join(', ')})" do
189
+ it 'does not match given multiple bad values' do
181
190
  expect(model).not_to allow_value(*bad_values).for(:attr)
182
191
  end
183
192
 
184
- it "rejects a mix of both good and bad values" do
185
- expect(model).not_to allow_value('12345', *bad_values).for(:attr)
193
+ it "does not match given good values along with bad values" do
194
+ message = %{Expected errors when attr is set to "12345",\ngot no errors}
195
+
196
+ expect {
197
+ expect(model).not_to allow_value('12345', *bad_values).for(:attr)
198
+ }.to fail_with_message(message)
186
199
  end
187
200
  end
188
201
 
@@ -232,19 +245,22 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
232
245
  context 'when the value is outside of the range of the column' do
233
246
  context 'not qualified with strict' do
234
247
  it 'rejects, failing with the correct message' do
235
- attribute_options = { type: :integer, options: { limit: 2 } }
248
+ type = :integer
249
+ attribute_options = { type: type, options: { limit: 2 } }
236
250
  record = define_model(:example, attr: attribute_options).new
237
251
  assertion = -> { expect(record).to allow_value(100000).for(:attr) }
252
+ column_type_class = column_type_class_for(type)
238
253
  message = <<-MESSAGE.strip_heredoc.strip
239
254
  Did not expect errors when attr is set to 100000,
240
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
255
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
241
256
  MESSAGE
242
257
  expect(&assertion).to fail_with_message(message)
243
258
  end
244
259
 
245
260
  context 'qualified with a message' do
246
261
  it 'ignores any specified message, failing with the correct message' do
247
- attribute_options = { type: :integer, options: { limit: 2 } }
262
+ type = :integer
263
+ attribute_options = { type: type, options: { limit: 2 } }
248
264
  record = define_model(:example, attr: attribute_options).new
249
265
  assertion = -> do
250
266
  expect(record).
@@ -252,9 +268,10 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
252
268
  for(:attr).
253
269
  with_message('some message')
254
270
  end
271
+ column_type_class = column_type_class_for(type)
255
272
  message = <<-MESSAGE.strip_heredoc.strip
256
273
  Did not expect errors to include "some message" when attr is set to 100000,
257
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
274
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
258
275
  MESSAGE
259
276
  expect(&assertion).to fail_with_message(message)
260
277
  end
@@ -264,7 +281,8 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
264
281
  if active_model_supports_strict?
265
282
  context 'qualified with strict' do
266
283
  it 'rejects, failing with the correct message' do
267
- attribute_options = { type: :integer, options: { limit: 2 } }
284
+ type = :integer
285
+ attribute_options = { type: type, options: { limit: 2 } }
268
286
  record = define_model(:example, attr: attribute_options).new
269
287
  assertion = -> do
270
288
  expect(record).
@@ -272,16 +290,18 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
272
290
  for(:attr).
273
291
  strict
274
292
  end
293
+ column_type_class = column_type_class_for(type)
275
294
  message = <<-MESSAGE.strip_heredoc.strip
276
295
  Did not expect an exception to have been raised when attr is set to 100000,
277
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
296
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
278
297
  MESSAGE
279
298
  expect(&assertion).to fail_with_message(message)
280
299
  end
281
300
 
282
301
  context 'qualified with a message' do
283
302
  it 'ignores any specified message' do
284
- attribute_options = { type: :integer, options: { limit: 2 } }
303
+ type = :integer
304
+ attribute_options = { type: type, options: { limit: 2 } }
285
305
  record = define_model(:example, attr: attribute_options).new
286
306
  assertion = -> do
287
307
  expect(record).
@@ -290,9 +310,10 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
290
310
  with_message('some message').
291
311
  strict
292
312
  end
313
+ column_type_class = column_type_class_for(type)
293
314
  message = <<-MESSAGE.strip_heredoc.strip
294
315
  Did not expect exception to include "some message" when attr is set to 100000,
295
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
316
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
296
317
  MESSAGE
297
318
  expect(&assertion).to fail_with_message(message)
298
319
  end
@@ -301,4 +322,50 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
301
322
  end
302
323
  end
303
324
  end
325
+
326
+ context 'when the attribute writer method ignores a non-nil value' do
327
+ context 'when the attribute has a reader method' do
328
+ it 'raises a CouldNotSetAttributeError' do
329
+ model = define_active_model_class 'Example' do
330
+ attr_reader :name
331
+
332
+ def name=(_value)
333
+ nil
334
+ end
335
+ end
336
+
337
+ assertion = -> {
338
+ expect(model.new).to allow_value('anything').for(:name)
339
+ }
340
+
341
+ expect(&assertion).to raise_error(
342
+ Shoulda::Matchers::ActiveModel::AllowValueMatcher::CouldNotSetAttributeError
343
+ )
344
+ end
345
+ end
346
+ end
347
+
348
+ context 'when the attribute writer method ignores a nil value' do
349
+ context 'when the attribute has a reader method' do
350
+ it 'raises a CouldNotSetAttribute error' do
351
+ model = define_active_model_class 'Example' do
352
+ attr_reader :name
353
+
354
+ def name=(value)
355
+ @name = value unless value.nil?
356
+ end
357
+ end
358
+
359
+ record = model.new(name: 'some name')
360
+
361
+ assertion = -> {
362
+ expect(record).to allow_value(nil).for(:name)
363
+ }
364
+
365
+ expect(&assertion).to raise_error(
366
+ Shoulda::Matchers::ActiveModel::AllowValueMatcher::CouldNotSetAttributeError
367
+ )
368
+ end
369
+ end
370
+ end
304
371
  end
@@ -83,19 +83,22 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
83
83
  context 'when the value is outside of the range of the column' do
84
84
  context 'not qualified with strict' do
85
85
  it 'accepts, failing with the correct message' do
86
- attribute_options = { type: :integer, options: { limit: 2 } }
86
+ type = :integer
87
+ attribute_options = { type: type, options: { limit: 2 } }
87
88
  record = define_model(:example, attr: attribute_options).new
88
89
  assertion = -> { expect(record).not_to disallow_value(100000).for(:attr) }
90
+ column_type_class = column_type_class_for(type)
89
91
  message = <<-MESSAGE.strip_heredoc.strip
90
92
  Did not expect errors when attr is set to 100000,
91
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
93
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
92
94
  MESSAGE
93
95
  expect(&assertion).to fail_with_message(message)
94
96
  end
95
97
 
96
98
  context 'qualified with a message' do
97
99
  it 'ignores any specified message, failing with the correct message' do
98
- attribute_options = { type: :integer, options: { limit: 2 } }
100
+ type = :integer
101
+ attribute_options = { type: type, options: { limit: 2 } }
99
102
  record = define_model(:example, attr: attribute_options).new
100
103
  assertion = -> do
101
104
  expect(record).
@@ -103,9 +106,10 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
103
106
  for(:attr).
104
107
  with_message('some message')
105
108
  end
109
+ column_type_class = column_type_class_for(type)
106
110
  message = <<-MESSAGE.strip_heredoc.strip
107
111
  Did not expect errors to include "some message" when attr is set to 100000,
108
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
112
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
109
113
  MESSAGE
110
114
  expect(&assertion).to fail_with_message(message)
111
115
  end
@@ -115,7 +119,8 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
115
119
  if active_model_supports_strict?
116
120
  context 'qualified with strict' do
117
121
  it 'accepts, failing with the correct message' do
118
- attribute_options = { type: :integer, options: { limit: 2 } }
122
+ type = :integer
123
+ attribute_options = { type: type, options: { limit: 2 } }
119
124
  record = define_model(:example, attr: attribute_options).new
120
125
  assertion = -> do
121
126
  expect(record).
@@ -123,16 +128,18 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
123
128
  for(:attr).
124
129
  strict
125
130
  end
131
+ column_type_class = column_type_class_for(type)
126
132
  message = <<-MESSAGE.strip_heredoc.strip
127
133
  Did not expect an exception to have been raised when attr is set to 100000,
128
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
134
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
129
135
  MESSAGE
130
136
  expect(&assertion).to fail_with_message(message)
131
137
  end
132
138
 
133
139
  context 'qualified with a message' do
134
140
  it 'ignores any specified message' do
135
- attribute_options = { type: :integer, options: { limit: 2 } }
141
+ type = :integer
142
+ attribute_options = { type: type, options: { limit: 2 } }
136
143
  record = define_model(:example, attr: attribute_options).new
137
144
  assertion = -> do
138
145
  expect(record).
@@ -141,9 +148,10 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
141
148
  with_message('some message').
142
149
  strict
143
150
  end
151
+ column_type_class = column_type_class_for(type)
144
152
  message = <<-MESSAGE.strip_heredoc.strip
145
153
  Did not expect exception to include "some message" when attr is set to 100000,
146
- got RangeError: "100000 is out of range for ActiveRecord::Type::Integer with limit 2"
154
+ got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
147
155
  MESSAGE
148
156
  expect(&assertion).to fail_with_message(message)
149
157
  end
@@ -5,6 +5,40 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
5
5
 
6
6
  it_behaves_like 'a numerical submatcher'
7
7
 
8
+ shared_examples_for 'strict qualifier' do
9
+ def validation_qualifier
10
+ matcher_qualifier.to_s.gsub(/^is_/, '').to_sym
11
+ end
12
+
13
+ context 'asserting strict validation when validating strictly' do
14
+ it 'accepts' do
15
+ record = instance_with_validations(
16
+ validation_qualifier => 1,
17
+ strict: true
18
+ )
19
+ expect(record).to matcher.__send__(matcher_qualifier, 1).strict
20
+ end
21
+ end
22
+
23
+ context 'asserting non-strict validation when validating strictly' do
24
+ it 'rejects' do
25
+ pending 'This needs to be fixed'
26
+ record = instance_with_validations(
27
+ validation_qualifier => 1,
28
+ strict: true
29
+ )
30
+ expect(record).not_to matcher.__send__(matcher_qualifier, 1)
31
+ end
32
+ end
33
+
34
+ context 'asserting strict validation when not validating strictly' do
35
+ it 'rejects' do
36
+ record = instance_with_validations(validation_qualifier => 1)
37
+ expect(record).not_to matcher.__send__(matcher_qualifier, 1).strict
38
+ end
39
+ end
40
+ end
41
+
8
42
  context 'when initialized without correct numerical matcher' do
9
43
  it 'raises an argument error' do
10
44
  fake_matcher = matcher
@@ -18,6 +52,12 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
18
52
  end
19
53
 
20
54
  context 'is_greater_than' do
55
+ include_examples 'strict qualifier' do
56
+ def matcher_qualifier
57
+ :is_greater_than
58
+ end
59
+ end
60
+
21
61
  it do
22
62
  expect(instance_with_validations(greater_than: 2))
23
63
  .to matcher.is_greater_than(2)
@@ -38,7 +78,13 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
38
78
  end
39
79
  end
40
80
 
41
- context 'greater_than_or_equal_to' do
81
+ context 'is_greater_than_or_equal_to' do
82
+ include_examples 'strict qualifier' do
83
+ def matcher_qualifier
84
+ :is_greater_than_or_equal_to
85
+ end
86
+ end
87
+
42
88
  it do
43
89
  expect(instance_with_validations(greater_than_or_equal_to: 2))
44
90
  .to matcher.is_greater_than_or_equal_to(2)
@@ -60,7 +106,13 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
60
106
  end
61
107
  end
62
108
 
63
- context 'less_than' do
109
+ context 'is_less_than' do
110
+ include_examples 'strict qualifier' do
111
+ def matcher_qualifier
112
+ :is_less_than
113
+ end
114
+ end
115
+
64
116
  it do
65
117
  expect(instance_with_validations(less_than: 2))
66
118
  .to matcher.is_less_than(2)
@@ -82,7 +134,13 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
82
134
  end
83
135
  end
84
136
 
85
- context 'less_than_or_equal_to' do
137
+ context 'is_less_than_or_equal_to' do
138
+ include_examples 'strict qualifier' do
139
+ def matcher_qualifier
140
+ :is_less_than_or_equal_to
141
+ end
142
+ end
143
+
86
144
  it do
87
145
  expect(instance_with_validations(less_than_or_equal_to: 2))
88
146
  .to matcher.is_less_than_or_equal_to(2)
@@ -105,6 +163,12 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
105
163
  end
106
164
 
107
165
  context 'is_equal_to' do
166
+ include_examples 'strict qualifier' do
167
+ def matcher_qualifier
168
+ :is_equal_to
169
+ end
170
+ end
171
+
108
172
  it do
109
173
  expect(instance_with_validations(equal_to: 0))
110
174
  .to matcher.is_equal_to(0)
@@ -133,6 +197,26 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
133
197
  end
134
198
  end
135
199
 
200
+ context 'qualified with on and validating with on' do
201
+ it 'accepts' do
202
+ expect(instance_with_validations(on: :customizable)).
203
+ to matcher.on(:customizable)
204
+ end
205
+ end
206
+
207
+ context 'qualified with on but not validating with on' do
208
+ it 'accepts since the validation never considers a context' do
209
+ expect(instance_with_validations).to matcher.on(:customizable)
210
+ end
211
+ end
212
+
213
+ context 'not qualified with on but validating with on' do
214
+ it 'rejects since the validation never runs' do
215
+ expect(instance_with_validations(on: :customizable)).
216
+ not_to matcher
217
+ end
218
+ end
219
+
136
220
  describe '#comparison_description' do
137
221
  [{ operator: :>, value: 0, expectation: 'greater than 0' },
138
222
  { operator: :>=, value: -1.0, expectation: 'greater than or equal to -1.0' },
@@ -150,19 +234,27 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
150
234
  end
151
235
  end
152
236
 
237
+ def model_with_validations(options = {})
238
+ define_model :example, attribute_name => :string do |model|
239
+ model.validates_numericality_of(attribute_name, options)
240
+ model.attr_accessible(attribute_name)
241
+ end
242
+ end
243
+
153
244
  def instance_with_validations(options = {})
154
- define_model :example, attr: :string do
155
- validates_numericality_of :attr, options
156
- attr_accessible :attr
157
- end.new
245
+ model_with_validations(options).new(attribute_name => '1')
158
246
  end
159
247
 
160
248
  def instance_without_validations
161
- define_model :example, attr: :string do
162
- attr_accessible :attr
249
+ define_model :example, attribute_name => :string do |model|
250
+ model.attr_accessible(attribute_name)
163
251
  end.new
164
252
  end
165
253
 
254
+ def attribute_name
255
+ :attr
256
+ end
257
+
166
258
  def matcher
167
259
  validate_numericality_of(:attr)
168
260
  end
@@ -45,6 +45,44 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::EvenNumberMatcher
45
45
  end
46
46
  end
47
47
 
48
+ context 'asserting strict validation when validating strictly' do
49
+ it 'accepts' do
50
+ expect(validating_even_number(strict: true)).to subject.strict
51
+ end
52
+ end
53
+
54
+ context 'asserting non-strict validation when validating strictly' do
55
+ it 'rejects' do
56
+ pending 'This needs to be fixed'
57
+ expect(validating_even_number(strict: true)).not_to subject
58
+ end
59
+ end
60
+
61
+ context 'asserting strict validation when not validating strictly' do
62
+ it 'rejects' do
63
+ expect(validating_even_number).not_to subject.strict
64
+ end
65
+ end
66
+
67
+ context 'qualified with on and validating with on' do
68
+ it 'accepts' do
69
+ expect(validating_even_number(on: :customizable)).
70
+ to subject.on(:customizable)
71
+ end
72
+ end
73
+
74
+ context 'qualified with on but not validating with on' do
75
+ it 'accepts since the validation never considers a context' do
76
+ expect(validating_even_number).to subject.on(:customizable)
77
+ end
78
+ end
79
+
80
+ context 'not qualified with on but validating with on' do
81
+ it 'rejects since the validation never runs' do
82
+ expect(validating_even_number(on: :customizable)).
83
+ not_to subject
84
+ end
85
+ end
48
86
 
49
87
  def validating_even_number(options = {})
50
88
  define_model :example, attr: :string do
@@ -56,4 +94,4 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::EvenNumberMatcher
56
94
  define_model(:example, attr: :string).new
57
95
  end
58
96
 
59
- end
97
+ end