shoulda-matchers 3.0.0.rc1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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