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.
- checksums.yaml +4 -4
- data/Gemfile +2 -3
- data/Gemfile.lock +12 -41
- data/NEWS.md +118 -26
- data/README.md +34 -11
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +4 -0
- data/gemfiles/4.0.0.gemfile +2 -3
- data/gemfiles/4.0.0.gemfile.lock +47 -77
- data/gemfiles/4.0.1.gemfile +2 -3
- data/gemfiles/4.0.1.gemfile.lock +51 -79
- data/gemfiles/4.1.gemfile +2 -3
- data/gemfiles/4.1.gemfile.lock +73 -103
- data/gemfiles/4.2.gemfile +2 -3
- data/gemfiles/4.2.gemfile.lock +90 -124
- data/lib/shoulda/matchers.rb +1 -0
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +6 -8
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +1 -3
- data/lib/shoulda/matchers/action_controller/flash_store.rb +1 -8
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +140 -88
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +2 -5
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +5 -10
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +2 -4
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +1 -3
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +3 -5
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -7
- data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +35 -9
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model.rb +57 -1
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +2 -5
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +162 -54
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -2
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +1 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +24 -11
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +0 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +2 -1
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +15 -13
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +4 -4
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +8 -8
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +8 -8
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +12 -14
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +10 -4
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +0 -3
- data/lib/shoulda/matchers/active_model/validator.rb +0 -8
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +4 -6
- data/lib/shoulda/matchers/active_record/association_matcher.rb +58 -43
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +3 -5
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +3 -5
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +1 -4
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +3 -5
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +7 -7
- data/lib/shoulda/matchers/doublespeak/double.rb +10 -1
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +13 -5
- data/lib/shoulda/matchers/doublespeak/method_call.rb +10 -1
- data/lib/shoulda/matchers/doublespeak/object_double.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/world.rb +10 -0
- data/lib/shoulda/matchers/error.rb +4 -0
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +11 -10
- data/lib/shoulda/matchers/integrations/libraries.rb +1 -0
- data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
- data/lib/shoulda/matchers/integrations/libraries/active_model.rb +1 -1
- data/lib/shoulda/matchers/integrations/libraries/active_record.rb +1 -1
- data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -1
- data/lib/shoulda/matchers/integrations/libraries/routing.rb +27 -0
- data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +2 -2
- data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
- data/lib/shoulda/matchers/routing.rb +10 -0
- data/lib/shoulda/matchers/version.rb +1 -1
- data/script/SUPPORTED_VERSIONS +1 -1
- data/spec/acceptance/independent_matchers_spec.rb +103 -42
- data/spec/doublespeak_spec_helper.rb +5 -1
- data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +34 -11
- data/spec/support/acceptance/helpers/rspec_helpers.rb +9 -13
- data/spec/support/acceptance/helpers/step_helpers.rb +13 -0
- data/spec/support/acceptance/matchers/have_output.rb +1 -1
- data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +1 -1
- data/spec/support/tests/command_runner.rb +5 -1
- data/spec/support/unit/helpers/active_record_versions.rb +0 -4
- data/spec/support/unit/shared_examples/set_session_or_flash.rb +8 -3
- data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +198 -39
- data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +269 -102
- data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +24 -0
- data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +118 -101
- data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -82
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +148 -121
- data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +20 -8
- data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +64 -183
- data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +14 -0
- data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +60 -0
- data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +23 -7
- data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +242 -0
- data/spec/unit_spec_helper.rb +4 -0
- data/tasks/documentation.rb +35 -0
- metadata +9 -8
- data/Guardfile +0 -5
- data/cucumber.yml +0 -1
- 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, []).
|
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).
|
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).
|
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
|
-
|
245
|
-
context 'when the
|
246
|
-
context '
|
247
|
-
it '
|
248
|
-
|
249
|
-
|
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
|
-
|
261
|
-
|
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
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
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
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
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
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
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
|
-
|
333
|
-
|
325
|
+
def name=(_value)
|
326
|
+
nil
|
327
|
+
end
|
334
328
|
end
|
335
|
-
end
|
336
329
|
|
337
|
-
|
338
|
-
|
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
|
-
|
342
|
-
|
343
|
-
)
|
337
|
+
expect(&assertion).not_to raise_error
|
338
|
+
end
|
344
339
|
end
|
345
|
-
end
|
346
|
-
end
|
347
340
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
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
|
-
|
355
|
-
|
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
|
-
|
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
|
-
|
362
|
-
|
363
|
-
|
369
|
+
def name=(_value)
|
370
|
+
@name = 'constant name'
|
371
|
+
end
|
372
|
+
end
|
364
373
|
|
365
|
-
|
366
|
-
|
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
|
data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb
CHANGED
@@ -1,22 +1,19 @@
|
|
1
1
|
require 'unit_spec_helper'
|
2
2
|
|
3
3
|
describe Shoulda::Matchers::ActiveModel::NumericalityMatchers::ComparisonMatcher do
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
55
|
-
include_examples 'strict qualifier'
|
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
|
-
|
63
|
-
|
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
|
-
|
68
|
-
|
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
|
-
|
73
|
-
|
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
|
-
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
90
|
-
|
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
|
-
|
95
|
-
|
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
|
-
|
100
|
-
|
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
|
-
|
105
|
-
|
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
|
-
|
110
|
-
|
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
|
-
|
118
|
-
|
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
|
-
|
123
|
-
|
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
|
-
|
128
|
-
|
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
|
-
|
133
|
-
|
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
|
-
|
138
|
-
|
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
|
-
|
146
|
-
|
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
|
-
|
151
|
-
|
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
|
-
|
156
|
-
|
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
|
-
|
161
|
-
|
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
|
-
|
166
|
-
|
167
|
-
def matcher_qualifier
|
168
|
-
:is_equal_to
|
169
|
-
end
|
184
|
+
def operator
|
185
|
+
:<=
|
170
186
|
end
|
171
187
|
|
172
|
-
|
173
|
-
|
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
|
-
|
179
|
-
|
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
|
-
|
184
|
-
|
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
|
-
|
189
|
-
|
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
|
-
|
194
|
-
|
195
|
-
|
196
|
-
expect(
|
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
|
-
|
201
|
-
|
202
|
-
expect(instance_with_validations(on: :customizable)).
|
203
|
-
to matcher.on(:customizable)
|
220
|
+
def operator
|
221
|
+
:==
|
204
222
|
end
|
205
|
-
end
|
206
223
|
|
207
|
-
|
208
|
-
|
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
|
-
|
214
|
-
it '
|
215
|
-
|
216
|
-
|
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
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
267
|
+
def model_without_validations
|
249
268
|
define_model :example, attribute_name => :string do |model|
|
250
269
|
model.attr_accessible(attribute_name)
|
251
|
-
end
|
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
|
259
|
-
|
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
|