shoulda-matchers 3.0.0.rc1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -3
  3. data/Gemfile.lock +12 -41
  4. data/NEWS.md +118 -26
  5. data/README.md +34 -11
  6. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -0
  7. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +4 -0
  8. data/gemfiles/4.0.0.gemfile +2 -3
  9. data/gemfiles/4.0.0.gemfile.lock +47 -77
  10. data/gemfiles/4.0.1.gemfile +2 -3
  11. data/gemfiles/4.0.1.gemfile.lock +51 -79
  12. data/gemfiles/4.1.gemfile +2 -3
  13. data/gemfiles/4.1.gemfile.lock +73 -103
  14. data/gemfiles/4.2.gemfile +2 -3
  15. data/gemfiles/4.2.gemfile.lock +90 -124
  16. data/lib/shoulda/matchers.rb +1 -0
  17. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +6 -8
  18. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +1 -3
  19. data/lib/shoulda/matchers/action_controller/flash_store.rb +1 -8
  20. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +140 -88
  21. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +2 -5
  22. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +5 -10
  23. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +2 -4
  24. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -3
  25. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +3 -5
  26. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -7
  27. data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +35 -9
  28. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -3
  29. data/lib/shoulda/matchers/active_model.rb +57 -1
  30. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +2 -5
  31. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +162 -54
  32. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -2
  33. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +1 -3
  34. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +24 -11
  35. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +4 -3
  36. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +0 -2
  37. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +4 -3
  38. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +2 -1
  39. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +15 -13
  40. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +3 -3
  41. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +3 -3
  42. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +4 -4
  43. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +8 -8
  44. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +8 -8
  45. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +12 -14
  46. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +10 -4
  47. data/lib/shoulda/matchers/active_model/validation_matcher.rb +0 -3
  48. data/lib/shoulda/matchers/active_model/validator.rb +0 -8
  49. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +4 -6
  50. data/lib/shoulda/matchers/active_record/association_matcher.rb +58 -43
  51. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +2 -2
  52. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +3 -5
  53. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +3 -5
  54. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +1 -4
  55. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +3 -5
  56. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +7 -7
  57. data/lib/shoulda/matchers/doublespeak/double.rb +10 -1
  58. data/lib/shoulda/matchers/doublespeak/double_collection.rb +13 -5
  59. data/lib/shoulda/matchers/doublespeak/method_call.rb +10 -1
  60. data/lib/shoulda/matchers/doublespeak/object_double.rb +2 -1
  61. data/lib/shoulda/matchers/doublespeak/world.rb +10 -0
  62. data/lib/shoulda/matchers/error.rb +4 -0
  63. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +11 -10
  64. data/lib/shoulda/matchers/integrations/libraries.rb +1 -0
  65. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  66. data/lib/shoulda/matchers/integrations/libraries/active_model.rb +1 -1
  67. data/lib/shoulda/matchers/integrations/libraries/active_record.rb +1 -1
  68. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -1
  69. data/lib/shoulda/matchers/integrations/libraries/routing.rb +27 -0
  70. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  71. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  72. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  73. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  74. data/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +2 -2
  75. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  76. data/lib/shoulda/matchers/routing.rb +10 -0
  77. data/lib/shoulda/matchers/version.rb +1 -1
  78. data/script/SUPPORTED_VERSIONS +1 -1
  79. data/spec/acceptance/independent_matchers_spec.rb +103 -42
  80. data/spec/doublespeak_spec_helper.rb +5 -1
  81. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +34 -11
  82. data/spec/support/acceptance/helpers/rspec_helpers.rb +9 -13
  83. data/spec/support/acceptance/helpers/step_helpers.rb +13 -0
  84. data/spec/support/acceptance/matchers/have_output.rb +1 -1
  85. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +1 -1
  86. data/spec/support/tests/command_runner.rb +5 -1
  87. data/spec/support/unit/helpers/active_record_versions.rb +0 -4
  88. data/spec/support/unit/shared_examples/set_session_or_flash.rb +8 -3
  89. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +198 -39
  90. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +269 -102
  91. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +24 -0
  92. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +118 -101
  93. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -82
  94. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +148 -121
  95. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +20 -8
  96. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +64 -183
  97. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +14 -0
  98. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +60 -0
  99. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +23 -7
  100. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +242 -0
  101. data/spec/unit_spec_helper.rb +4 -0
  102. data/tasks/documentation.rb +35 -0
  103. metadata +9 -8
  104. data/Guardfile +0 -5
  105. data/cucumber.yml +0 -1
  106. data/lib/shoulda/matchers/active_model/validator_with_captured_range_error.rb +0 -12
@@ -40,4 +40,28 @@ describe Shoulda::Matchers::ActionController::SetFlashMatcher, type: :controller
40
40
  expect(controller).not_to set_flash.now['key for flash']
41
41
  end
42
42
  end
43
+
44
+ context 'when the now qualifier is called after the key is set' do
45
+ it 'raises a QualifierOrderError' do
46
+ controller = build_fake_response
47
+
48
+ usage = lambda do
49
+ expect(controller).to set_flash['any key'].now
50
+ end
51
+
52
+ expect(&usage).to raise_error(described_class::QualifierOrderError)
53
+ end
54
+ end
55
+
56
+ context 'when the now qualifier is called after the to qualifier' do
57
+ it 'raises a QualifierOrderError' do
58
+ controller = build_fake_response
59
+
60
+ usage = lambda do
61
+ expect(controller).to set_flash.to('any value').now
62
+ end
63
+
64
+ expect(&usage).to raise_error(described_class::QualifierOrderError)
65
+ end
66
+ end
43
67
  end
@@ -1,6 +1,6 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
- describe Shoulda::Matchers::ActiveModel do
3
+ describe Shoulda::Matchers::ActiveModel, type: :model do
4
4
  describe '#allow_values' do
5
5
  it 'is aliased to #allow_value' do
6
6
  expect(method(:allow_values)).to eq(method(:allow_value))
@@ -62,7 +62,9 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
62
62
 
63
63
  it 'rejects several bad values' do
64
64
  expect(validating_format(with: /abc/)).
65
- not_to allow_value('xyz', 'zyx', nil, []).for(:attr)
65
+ not_to allow_value('xyz', 'zyx', nil, []).
66
+ for(:attr).
67
+ ignoring_interference_by_writer
66
68
  end
67
69
  end
68
70
 
@@ -182,12 +184,18 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
182
184
 
183
185
  it 'does not match given a bad value' do
184
186
  bad_values.each do |bad_value|
185
- expect(model).not_to allow_value(bad_value).for(:attr)
187
+ expect(model).
188
+ not_to allow_value(bad_value).
189
+ for(:attr).
190
+ ignoring_interference_by_writer
186
191
  end
187
192
  end
188
193
 
189
194
  it 'does not match given multiple bad values' do
190
- expect(model).not_to allow_value(*bad_values).for(:attr)
195
+ expect(model).
196
+ not_to allow_value(*bad_values).
197
+ for(:attr).
198
+ ignoring_interference_by_writer
191
199
  end
192
200
 
193
201
  it "does not match given good values along with bad values" do
@@ -241,130 +249,139 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher, type: :model do
241
249
  end
242
250
  end
243
251
 
244
- if active_record_can_raise_range_error?
245
- context 'when the value is outside of the range of the column' do
246
- context 'not qualified with strict' do
247
- it 'rejects, failing with the correct message' do
248
- type = :integer
249
- attribute_options = { type: type, options: { limit: 2 } }
250
- record = define_model(:example, attr: attribute_options).new
251
- assertion = -> { expect(record).to allow_value(100000).for(:attr) }
252
- column_type_class = column_type_class_for(type)
253
- message = <<-MESSAGE.strip_heredoc.strip
254
- Did not expect errors when attr is set to 100000,
255
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
256
- MESSAGE
257
- expect(&assertion).to fail_with_message(message)
258
- end
252
+ context 'when the attribute interferes with attempts to be set' do
253
+ context 'when the matcher has not been qualified with #ignoring_interference_by_writer' do
254
+ context 'when the attribute cannot be changed from nil to non-nil' do
255
+ it 'raises a CouldNotSetAttributeError' do
256
+ model = define_active_model_class 'Example' do
257
+ attr_reader :name
259
258
 
260
- context 'qualified with a message' do
261
- it 'ignores any specified message, failing with the correct message' do
262
- type = :integer
263
- attribute_options = { type: type, options: { limit: 2 } }
264
- record = define_model(:example, attr: attribute_options).new
265
- assertion = -> do
266
- expect(record).
267
- to allow_value(100000).
268
- for(:attr).
269
- with_message('some message')
259
+ def name=(_value)
260
+ nil
270
261
  end
271
- column_type_class = column_type_class_for(type)
272
- message = <<-MESSAGE.strip_heredoc.strip
273
- Did not expect errors to include "some message" when attr is set to 100000,
274
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
275
- MESSAGE
276
- expect(&assertion).to fail_with_message(message)
277
262
  end
263
+
264
+ assertion = -> {
265
+ expect(model.new).to allow_value('anything').for(:name)
266
+ }
267
+
268
+ expect(&assertion).to raise_error(
269
+ described_class::CouldNotSetAttributeError
270
+ )
278
271
  end
279
272
  end
280
273
 
281
- if active_model_supports_strict?
282
- context 'qualified with strict' do
283
- it 'rejects, failing with the correct message' do
284
- type = :integer
285
- attribute_options = { type: type, options: { limit: 2 } }
286
- record = define_model(:example, attr: attribute_options).new
287
- assertion = -> do
288
- expect(record).
289
- to allow_value(100000).
290
- for(:attr).
291
- strict
274
+ context 'when the attribute cannot be changed from non-nil to nil' do
275
+ it 'raises a CouldNotSetAttribute error' do
276
+ model = define_active_model_class 'Example' do
277
+ attr_reader :name
278
+
279
+ def name=(value)
280
+ @name = value unless value.nil?
292
281
  end
293
- column_type_class = column_type_class_for(type)
294
- message = <<-MESSAGE.strip_heredoc.strip
295
- Did not expect an exception to have been raised when attr is set to 100000,
296
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
297
- MESSAGE
298
- expect(&assertion).to fail_with_message(message)
299
282
  end
300
283
 
301
- context 'qualified with a message' do
302
- it 'ignores any specified message' do
303
- type = :integer
304
- attribute_options = { type: type, options: { limit: 2 } }
305
- record = define_model(:example, attr: attribute_options).new
306
- assertion = -> do
307
- expect(record).
308
- to allow_value(100000).
309
- for(:attr).
310
- with_message('some message').
311
- strict
312
- end
313
- column_type_class = column_type_class_for(type)
314
- message = <<-MESSAGE.strip_heredoc.strip
315
- Did not expect exception to include "some message" when attr is set to 100000,
316
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
317
- MESSAGE
318
- expect(&assertion).to fail_with_message(message)
284
+ record = model.new(name: 'some name')
285
+
286
+ assertion = -> {
287
+ expect(record).to allow_value(nil).for(:name)
288
+ }
289
+
290
+ expect(&assertion).to raise_error(
291
+ described_class::CouldNotSetAttributeError
292
+ )
293
+ end
294
+ end
295
+
296
+ context 'when the attribute cannot be changed from a non-nil value to another non-nil value' do
297
+ it 'raises a CouldNotSetAttribute error' do
298
+ model = define_active_model_class 'Example' do
299
+ attr_reader :name
300
+
301
+ def name=(_value)
302
+ @name = 'constant name'
319
303
  end
320
304
  end
305
+
306
+ record = model.new(name: 'some name')
307
+
308
+ assertion = -> {
309
+ expect(record).to allow_value('another name').for(:name)
310
+ }
311
+
312
+ expect(&assertion).to raise_error(
313
+ described_class::CouldNotSetAttributeError
314
+ )
321
315
  end
322
316
  end
323
317
  end
324
- end
325
318
 
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
319
+ context 'when the matcher has been qualified with #ignoring_interference_by_writer' do
320
+ context 'when the attribute cannot be changed from nil to non-nil' do
321
+ it 'does not raise an error at all' do
322
+ model = define_active_model_class 'Example' do
323
+ attr_reader :name
331
324
 
332
- def name=(_value)
333
- nil
325
+ def name=(_value)
326
+ nil
327
+ end
334
328
  end
335
- end
336
329
 
337
- assertion = -> {
338
- expect(model.new).to allow_value('anything').for(:name)
339
- }
330
+ assertion = lambda do
331
+ expect(model.new).
332
+ to allow_value('anything').
333
+ for(:name).
334
+ ignoring_interference_by_writer
335
+ end
340
336
 
341
- expect(&assertion).to raise_error(
342
- Shoulda::Matchers::ActiveModel::AllowValueMatcher::CouldNotSetAttributeError
343
- )
337
+ expect(&assertion).not_to raise_error
338
+ end
344
339
  end
345
- end
346
- end
347
340
 
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
341
+ context 'when the attribute cannot be changed from non-nil to nil' do
342
+ it 'does not raise an error at all' do
343
+ model = define_active_model_class 'Example' do
344
+ attr_reader :name
345
+
346
+ def name=(value)
347
+ @name = value unless value.nil?
348
+ end
349
+ end
350
+
351
+ record = model.new(name: 'some name')
353
352
 
354
- def name=(value)
355
- @name = value unless value.nil?
353
+ assertion = lambda do
354
+ expect(record).
355
+ to allow_value(nil).
356
+ for(:name).
357
+ ignoring_interference_by_writer
356
358
  end
359
+
360
+ expect(&assertion).not_to raise_error
357
361
  end
362
+ end
358
363
 
359
- record = model.new(name: 'some name')
364
+ context 'when the attribute cannot be changed from a non-nil value to another non-nil value' do
365
+ it 'does not raise an error at all' do
366
+ model = define_active_model_class 'Example' do
367
+ attr_reader :name
360
368
 
361
- assertion = -> {
362
- expect(record).to allow_value(nil).for(:name)
363
- }
369
+ def name=(_value)
370
+ @name = 'constant name'
371
+ end
372
+ end
364
373
 
365
- expect(&assertion).to raise_error(
366
- Shoulda::Matchers::ActiveModel::AllowValueMatcher::CouldNotSetAttributeError
367
- )
374
+ record = model.new(name: 'some name')
375
+
376
+ assertion = lambda do
377
+ expect(record).
378
+ to allow_value('another name').
379
+ for(:name).
380
+ ignoring_interference_by_writer
381
+ end
382
+
383
+ expect(&assertion).not_to raise_error
384
+ end
368
385
  end
369
386
  end
370
387
  end
@@ -79,88 +79,6 @@ describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher, type: :model do
79
79
  end
80
80
  end
81
81
 
82
- if active_record_can_raise_range_error?
83
- context 'when the value is outside of the range of the column' do
84
- context 'not qualified with strict' do
85
- it 'accepts, failing with the correct message' do
86
- type = :integer
87
- attribute_options = { type: type, options: { limit: 2 } }
88
- record = define_model(:example, attr: attribute_options).new
89
- assertion = -> { expect(record).not_to disallow_value(100000).for(:attr) }
90
- column_type_class = column_type_class_for(type)
91
- message = <<-MESSAGE.strip_heredoc.strip
92
- Did not expect errors when attr is set to 100000,
93
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
94
- MESSAGE
95
- expect(&assertion).to fail_with_message(message)
96
- end
97
-
98
- context 'qualified with a message' do
99
- it 'ignores any specified message, failing with the correct message' do
100
- type = :integer
101
- attribute_options = { type: type, options: { limit: 2 } }
102
- record = define_model(:example, attr: attribute_options).new
103
- assertion = -> do
104
- expect(record).
105
- not_to disallow_value(100000).
106
- for(:attr).
107
- with_message('some message')
108
- end
109
- column_type_class = column_type_class_for(type)
110
- message = <<-MESSAGE.strip_heredoc.strip
111
- Did not expect errors to include "some message" when attr is set to 100000,
112
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
113
- MESSAGE
114
- expect(&assertion).to fail_with_message(message)
115
- end
116
- end
117
- end
118
-
119
- if active_model_supports_strict?
120
- context 'qualified with strict' do
121
- it 'accepts, failing with the correct message' do
122
- type = :integer
123
- attribute_options = { type: type, options: { limit: 2 } }
124
- record = define_model(:example, attr: attribute_options).new
125
- assertion = -> do
126
- expect(record).
127
- not_to disallow_value(100000).
128
- for(:attr).
129
- strict
130
- end
131
- column_type_class = column_type_class_for(type)
132
- message = <<-MESSAGE.strip_heredoc.strip
133
- Did not expect an exception to have been raised when attr is set to 100000,
134
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
135
- MESSAGE
136
- expect(&assertion).to fail_with_message(message)
137
- end
138
-
139
- context 'qualified with a message' do
140
- it 'ignores any specified message' do
141
- type = :integer
142
- attribute_options = { type: type, options: { limit: 2 } }
143
- record = define_model(:example, attr: attribute_options).new
144
- assertion = -> do
145
- expect(record).
146
- not_to disallow_value(100000).
147
- for(:attr).
148
- with_message('some message').
149
- strict
150
- end
151
- column_type_class = column_type_class_for(type)
152
- message = <<-MESSAGE.strip_heredoc.strip
153
- Did not expect exception to include "some message" when attr is set to 100000,
154
- got RangeError: "100000 is out of range for #{column_type_class} with limit 2"
155
- MESSAGE
156
- expect(&assertion).to fail_with_message(message)
157
- end
158
- end
159
- end
160
- end
161
- end
162
- end
163
-
164
82
  def matcher(value)
165
83
  described_class.new(value)
166
84
  end
@@ -1,22 +1,19 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
3
  describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher do
4
- subject { described_class.new(matcher, 0, :>) }
5
-
6
- it_behaves_like 'a numerical submatcher'
4
+ it_behaves_like 'a numerical submatcher' do
5
+ subject { build_matcher }
6
+ end
7
7
 
8
8
  shared_examples_for 'strict qualifier' do
9
- def validation_qualifier
10
- matcher_qualifier.to_s.gsub(/^is_/, '').to_sym
11
- end
12
-
13
9
  context 'asserting strict validation when validating strictly' do
14
10
  it 'accepts' do
15
11
  record = instance_with_validations(
16
12
  validation_qualifier => 1,
17
13
  strict: true
18
14
  )
19
- expect(record).to matcher.__send__(matcher_qualifier, 1).strict
15
+ matcher = build_matcher(operator: operator, value: 1).strict
16
+ expect(record).to matcher
20
17
  end
21
18
  end
22
19
 
@@ -27,209 +24,231 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
27
24
  validation_qualifier => 1,
28
25
  strict: true
29
26
  )
30
- expect(record).not_to matcher.__send__(matcher_qualifier, 1)
27
+ matcher = build_matcher(operator: operator, value: 1)
28
+ expect(record).not_to matcher
31
29
  end
32
30
  end
33
31
 
34
32
  context 'asserting strict validation when not validating strictly' do
35
33
  it 'rejects' do
36
34
  record = instance_with_validations(validation_qualifier => 1)
37
- expect(record).not_to matcher.__send__(matcher_qualifier, 1).strict
35
+ matcher = build_matcher(operator: operator, value: 1).strict
36
+ expect(record).not_to matcher
38
37
  end
39
38
  end
40
39
  end
41
40
 
42
41
  context 'when initialized without correct numerical matcher' do
43
- it 'raises an argument error' do
44
- fake_matcher = matcher
45
- class << fake_matcher
46
- undef_method :diff_to_compare
47
- end
48
- expect do
49
- described_class.new(fake_matcher, 0, :>)
50
- end.to raise_error ArgumentError
42
+ it 'raises an ArgumentError' do
43
+ numericality_matcher = double
44
+ expect { described_class.new(numericality_matcher, 0, :>) }.
45
+ to raise_error(ArgumentError)
51
46
  end
52
47
  end
53
48
 
54
- context 'is_greater_than' do
55
- include_examples 'strict qualifier' do
56
- def matcher_qualifier
57
- :is_greater_than
58
- end
59
- end
49
+ describe 'is_greater_than' do
50
+ include_examples 'strict qualifier'
60
51
 
61
52
  it do
62
- expect(instance_with_validations(greater_than: 2))
63
- .to matcher.is_greater_than(2)
53
+ record = instance_with_validations(greater_than: 1.5)
54
+ matcher = build_matcher(operator: :>, value: 2)
55
+ expect(record).not_to matcher
64
56
  end
65
57
 
66
58
  it do
67
- expect(instance_with_validations(greater_than: 1.5))
68
- .not_to matcher.is_greater_than(2)
59
+ record = instance_with_validations(greater_than: 2)
60
+ matcher = build_matcher(operator: :>, value: 2)
61
+ expect(record).to matcher
69
62
  end
70
63
 
71
64
  it do
72
- expect(instance_with_validations(greater_than: 2.5))
73
- .not_to matcher.is_greater_than(2)
65
+ record = instance_with_validations(greater_than: 2.5)
66
+ matcher = build_matcher(operator: :>, value: 2)
67
+ expect(record).not_to matcher
74
68
  end
75
69
 
76
70
  it do
77
- expect(instance_without_validations).not_to matcher.is_greater_than(2)
71
+ record = instance_without_validations
72
+ matcher = build_matcher(operator: :>, value: 2)
73
+ expect(record).not_to matcher
78
74
  end
79
- end
80
75
 
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
76
+ def operator
77
+ :>
78
+ end
79
+
80
+ def validation_qualifier
81
+ :greater_than
86
82
  end
83
+ end
84
+
85
+ describe 'is_greater_than_or_equal_to' do
86
+ include_examples 'strict qualifier'
87
87
 
88
88
  it do
89
- expect(instance_with_validations(greater_than_or_equal_to: 2))
90
- .to matcher.is_greater_than_or_equal_to(2)
89
+ record = instance_with_validations(greater_than_or_equal_to: 1.5)
90
+ matcher = build_matcher(operator: :>=, value: 2)
91
+ expect(record).not_to matcher
91
92
  end
92
93
 
93
94
  it do
94
- expect(instance_with_validations(greater_than_or_equal_to: 1.5))
95
- .not_to matcher.is_greater_than_or_equal_to(2)
95
+ record = instance_with_validations(greater_than_or_equal_to: 2)
96
+ matcher = build_matcher(operator: :>=, value: 2)
97
+ expect(record).to matcher
96
98
  end
97
99
 
98
100
  it do
99
- expect(instance_with_validations(greater_than_or_equal_to: 2.5))
100
- .not_to matcher.is_greater_than_or_equal_to(2)
101
+ record = instance_with_validations(greater_than_or_equal_to: 2.5)
102
+ matcher = build_matcher(operator: :>=, value: 2)
103
+ expect(record).not_to matcher
101
104
  end
102
105
 
103
106
  it do
104
- expect(instance_without_validations)
105
- .not_to matcher.is_greater_than_or_equal_to(2)
107
+ record = instance_without_validations
108
+ matcher = build_matcher(operator: :>=, value: 2)
109
+ expect(record).not_to matcher
106
110
  end
107
- end
108
111
 
109
- context 'is_less_than' do
110
- include_examples 'strict qualifier' do
111
- def matcher_qualifier
112
- :is_less_than
113
- end
112
+ def operator
113
+ :>=
114
114
  end
115
115
 
116
+ def validation_qualifier
117
+ :greater_than_or_equal_to
118
+ end
119
+ end
120
+
121
+ describe 'is_less_than' do
122
+ include_examples 'strict qualifier'
123
+
116
124
  it do
117
- expect(instance_with_validations(less_than: 2))
118
- .to matcher.is_less_than(2)
125
+ record = instance_with_validations(less_than: 1.5)
126
+ matcher = build_matcher(operator: :<, value: 2)
127
+ expect(record).not_to matcher
119
128
  end
120
129
 
121
130
  it do
122
- expect(instance_with_validations(less_than: 1.5))
123
- .not_to matcher.is_less_than(2)
131
+ record = instance_with_validations(less_than: 2)
132
+ matcher = build_matcher(operator: :<, value: 2)
133
+ expect(record).to matcher
124
134
  end
125
135
 
126
136
  it do
127
- expect(instance_with_validations(less_than: 2.5))
128
- .not_to matcher.is_less_than(2)
137
+ record = instance_with_validations(less_than: 2.5)
138
+ matcher = build_matcher(operator: :<, value: 2)
139
+ expect(record).not_to matcher
129
140
  end
130
141
 
131
142
  it do
132
- expect(instance_without_validations)
133
- .not_to matcher.is_less_than(2)
143
+ record = instance_without_validations
144
+ matcher = build_matcher(operator: :<, value: 2)
145
+ expect(record).not_to matcher
134
146
  end
135
- end
136
147
 
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
148
+ def operator
149
+ :<
142
150
  end
143
151
 
152
+ def validation_qualifier
153
+ :less_than
154
+ end
155
+ end
156
+
157
+ describe 'is_less_than_or_equal_to' do
158
+ include_examples 'strict qualifier'
159
+
144
160
  it do
145
- expect(instance_with_validations(less_than_or_equal_to: 2))
146
- .to matcher.is_less_than_or_equal_to(2)
161
+ record = instance_with_validations(less_than_or_equal_to: 1.5)
162
+ matcher = build_matcher(operator: :<=, value: 2)
163
+ expect(record).not_to matcher
147
164
  end
148
165
 
149
166
  it do
150
- expect(instance_with_validations(less_than_or_equal_to: 1.5))
151
- .not_to matcher.is_less_than_or_equal_to(2)
167
+ record = instance_with_validations(less_than_or_equal_to: 2)
168
+ matcher = build_matcher(operator: :<=, value: 2)
169
+ expect(record).to matcher
152
170
  end
153
171
 
154
172
  it do
155
- expect(instance_with_validations(less_than_or_equal_to: 2.5))
156
- .not_to matcher.is_less_than_or_equal_to(2)
173
+ record = instance_with_validations(less_than_or_equal_to: 2.5)
174
+ matcher = build_matcher(operator: :<=, value: 2)
175
+ expect(record).not_to matcher
157
176
  end
158
177
 
159
178
  it do
160
- expect(instance_without_validations)
161
- .not_to matcher.is_less_than_or_equal_to(2)
179
+ record = instance_without_validations
180
+ matcher = build_matcher(operator: :<=, value: 2)
181
+ expect(record).not_to matcher
162
182
  end
163
- end
164
183
 
165
- context 'is_equal_to' do
166
- include_examples 'strict qualifier' do
167
- def matcher_qualifier
168
- :is_equal_to
169
- end
184
+ def operator
185
+ :<=
170
186
  end
171
187
 
172
- it do
173
- expect(instance_with_validations(equal_to: 0))
174
- .to matcher.is_equal_to(0)
188
+ def validation_qualifier
189
+ :less_than_or_equal_to
175
190
  end
191
+ end
192
+
193
+ describe 'is_equal_to' do
194
+ include_examples 'strict qualifier'
176
195
 
177
196
  it do
178
- expect(instance_with_validations(equal_to: -0.5))
179
- .not_to matcher.is_equal_to(0)
197
+ record = instance_with_validations(equal_to: 1.5)
198
+ matcher = build_matcher(operator: :==, value: 2)
199
+ expect(record).not_to matcher
180
200
  end
181
201
 
182
202
  it do
183
- expect(instance_with_validations(equal_to: 0.5))
184
- .not_to matcher.is_equal_to(0)
203
+ record = instance_with_validations(equal_to: 2)
204
+ matcher = build_matcher(operator: :==, value: 2)
205
+ expect(record).to matcher
185
206
  end
186
207
 
187
208
  it do
188
- expect(instance_without_validations)
189
- .not_to matcher.is_equal_to(0)
209
+ record = instance_with_validations(equal_to: 2.5)
210
+ matcher = build_matcher(operator: :==, value: 2)
211
+ expect(record).not_to matcher
190
212
  end
191
- end
192
213
 
193
- context 'with_message' do
194
- it 'verifies the message for the validation' do
195
- instance = instance_with_validations(equal_to: 0, message: 'Must be zero')
196
- expect(instance).to matcher.is_equal_to(0).with_message('Must be zero')
214
+ it do
215
+ record = instance_without_validations
216
+ matcher = build_matcher(operator: :==, value: 2)
217
+ expect(record).not_to matcher
197
218
  end
198
- end
199
219
 
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)
220
+ def operator
221
+ :==
204
222
  end
205
- end
206
223
 
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)
224
+ def validation_qualifier
225
+ :equal_to
210
226
  end
211
227
  end
212
228
 
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
229
+ describe 'with_message' do
230
+ it 'verifies the message for the validation' do
231
+ instance = instance_with_validations(equal_to: 0, message: 'Must be zero')
232
+ matcher = build_matcher.with_message('Must be zero')
233
+ expect(instance).to matcher
217
234
  end
218
235
  end
219
236
 
220
237
  describe '#comparison_description' do
221
- [{ operator: :>, value: 0, expectation: 'greater than 0' },
222
- { operator: :>=, value: -1.0, expectation: 'greater than or equal to -1.0' },
223
- { operator: :==, value: 2.2, expectation: 'equal to 2.2' },
224
- { operator: :<, value: -3, expectation: 'less than -3' },
225
- { operator: :<=, value: 4, expectation: 'less than or equal to 4' },
226
- ].each do |h|
227
- context "with :#{h[:operator]} as operator and #{h[:value]} as value" do
228
- subject do
229
- described_class.new(matcher, h[:value], h[:operator])
230
- .comparison_description
238
+ tests = [
239
+ { operator: :>, value: 0, expectation: 'greater than 0' },
240
+ { operator: :>=, value: -1.0, expectation: 'greater than or equal to -1.0' },
241
+ { operator: :==, value: 2.2, expectation: 'equal to 2.2' },
242
+ { operator: :<, value: -3, expectation: 'less than -3' },
243
+ { operator: :<=, value: 4, expectation: 'less than or equal to 4' },
244
+ ]
245
+
246
+ tests.each do |test|
247
+ context "with :#{test[:operator]} as operator and #{test[:value]} as value" do
248
+ it do
249
+ matcher = build_matcher(operator: test[:operator], value: test[:value])
250
+ expect(matcher.comparison_description).to eq test[:expectation]
231
251
  end
232
- it { should eq h[:expectation] }
233
252
  end
234
253
  end
235
254
  end
@@ -245,17 +264,25 @@ describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher
245
264
  model_with_validations(options).new(attribute_name => '1')
246
265
  end
247
266
 
248
- def instance_without_validations
267
+ def model_without_validations
249
268
  define_model :example, attribute_name => :string do |model|
250
269
  model.attr_accessible(attribute_name)
251
- end.new
270
+ end
271
+ end
272
+
273
+ def instance_without_validations
274
+ model_without_validations.new
252
275
  end
253
276
 
254
277
  def attribute_name
255
278
  :attr
256
279
  end
257
280
 
258
- def matcher
259
- validate_numericality_of(:attr)
281
+ def build_matcher(operator: :==, value: 0)
282
+ described_class.new(numericality_matcher, value, operator).for(attribute_name)
283
+ end
284
+
285
+ def numericality_matcher
286
+ double(diff_to_compare: 1)
260
287
  end
261
288
  end