veto 0.0.1

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 (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +561 -0
  6. data/Rakefile +1 -0
  7. data/lib/veto/attribute_validator_factory.rb +32 -0
  8. data/lib/veto/builder.rb +65 -0
  9. data/lib/veto/conditions.rb +23 -0
  10. data/lib/veto/conditions_evaluator.rb +30 -0
  11. data/lib/veto/configuration.rb +42 -0
  12. data/lib/veto/errors.rb +35 -0
  13. data/lib/veto/exceptions.rb +5 -0
  14. data/lib/veto/model.rb +37 -0
  15. data/lib/veto/validator.rb +150 -0
  16. data/lib/veto/validators/abstract_validator.rb +15 -0
  17. data/lib/veto/validators/attribute_validator.rb +22 -0
  18. data/lib/veto/validators/custom_method_validator.rb +19 -0
  19. data/lib/veto/validators/exact_length_validator.rb +15 -0
  20. data/lib/veto/validators/format_validator.rb +15 -0
  21. data/lib/veto/validators/inclusion_validator.rb +16 -0
  22. data/lib/veto/validators/integer_validator.rb +17 -0
  23. data/lib/veto/validators/length_range_validator.rb +16 -0
  24. data/lib/veto/validators/max_length_validator.rb +15 -0
  25. data/lib/veto/validators/min_length_validator.rb +15 -0
  26. data/lib/veto/validators/not_null_validator.rb +14 -0
  27. data/lib/veto/validators/numeric_validator.rb +17 -0
  28. data/lib/veto/validators/presence_validator.rb +15 -0
  29. data/lib/veto/version.rb +3 -0
  30. data/lib/veto.rb +53 -0
  31. data/spec/attribute_validator_factory_spec.rb +72 -0
  32. data/spec/builder_spec.rb +38 -0
  33. data/spec/conditions_evaluator_spec.rb +90 -0
  34. data/spec/conditions_spec.rb +16 -0
  35. data/spec/configuration/message_spec.rb +30 -0
  36. data/spec/configuration_spec.rb +6 -0
  37. data/spec/errors_spec.rb +22 -0
  38. data/spec/model_spec.rb +67 -0
  39. data/spec/spec_helper.rb +6 -0
  40. data/spec/system/validator_spec.rb +380 -0
  41. data/spec/validator_spec.rb +119 -0
  42. data/spec/validators/exact_length_validator_spec.rb +37 -0
  43. data/spec/validators/format_validator_spec.rb +32 -0
  44. data/spec/validators/inclusion_validator_spec.rb +45 -0
  45. data/spec/validators/integer_validator_spec.rb +42 -0
  46. data/spec/validators/length_range_validator_spec.rb +55 -0
  47. data/spec/validators/max_length_validator_spec.rb +32 -0
  48. data/spec/validators/min_length_validator_spec.rb +32 -0
  49. data/spec/validators/not_null_validator_spec.rb +27 -0
  50. data/spec/validators/numeric_validator_spec.rb +42 -0
  51. data/spec/validators/presence_validator_spec.rb +47 -0
  52. data/spec/veto_spec.rb +24 -0
  53. data/veto.gemspec +24 -0
  54. metadata +161 -0
@@ -0,0 +1,380 @@
1
+ require 'spec_helper'
2
+ require 'veto'
3
+
4
+ describe Veto do
5
+ let(:entity){ stub }
6
+ let(:validator_class) { Class.new{ include Veto.validator }}
7
+ let(:validator) { validator_class.new(entity) }
8
+
9
+ describe 'built-in validations' do
10
+ let(:value) { 'abc123' }
11
+ let(:entity) {stub(:name => value)}
12
+ let(:errors) { validator.valid?; validator.errors.on(:name) }
13
+ let(:validator_type){ :presence }
14
+ let(:options) { true }
15
+ let(:validator_class) do
16
+ klass = Class.new{ include Veto.validator }
17
+ klass.validates :name, options
18
+ klass
19
+ end
20
+
21
+ describe 'exact_length' do
22
+ let(:options) {{:exact_length => 10}}
23
+
24
+ context 'when value exact length' do
25
+ let(:value) { 'abcdefghij' }
26
+ it { errors.must_be_nil }
27
+ end
28
+
29
+ context 'when value is too short' do
30
+ let(:value) { 'short' }
31
+ it { errors.must_equal ["is not 10 characters"] }
32
+ end
33
+
34
+ context 'when value is too long' do
35
+ let(:value) { 'this title is wayyyy to long' }
36
+ it { errors.must_equal ["is not 10 characters"] }
37
+ end
38
+
39
+ context 'when value is nil' do
40
+ let(:value) { nil }
41
+ it { errors.must_equal ["is not 10 characters"] }
42
+ end
43
+ end
44
+
45
+ describe 'format' do
46
+ let(:options) {{:format => /^\d+$/}}
47
+
48
+ context 'when value matches pattern' do
49
+ let(:value) { 123 }
50
+ it { errors.must_be_nil }
51
+ end
52
+
53
+ context 'when value does not match' do
54
+ let(:value) { 'abc' }
55
+ it { errors.must_equal ["is not valid"] }
56
+ end
57
+
58
+ context 'when value is nil' do
59
+ let(:value) { nil }
60
+ it { errors.must_equal ["is not valid"] }
61
+ end
62
+ end
63
+
64
+ describe 'inclusion' do
65
+ context 'when set is array' do
66
+ let(:options) {{:inclusion => %w(cat dog bird rabbit)}}
67
+
68
+ context 'when value is in set' do
69
+ let(:value) { 'cat' }
70
+ it { errors.must_be_nil }
71
+ end
72
+
73
+ context 'when value is not in set' do
74
+ let(:value) { 'goat' }
75
+ it { errors.must_equal ["is not in set: [\"cat\", \"dog\", \"bird\", \"rabbit\"]"]}
76
+ end
77
+ end
78
+
79
+ context 'when set is range' do
80
+ let(:options) {{:inclusion => 10..20}}
81
+
82
+ context 'when value is in set' do
83
+ let(:value) { 11 }
84
+ it { errors.must_be_nil }
85
+ end
86
+
87
+ context 'when value is not in set' do
88
+ let(:value) { 5 }
89
+ it { errors.must_equal ["is not in set: 10..20"] }
90
+ end
91
+ end
92
+ end
93
+
94
+ describe 'integer' do
95
+ let(:options) {{:integer => true}}
96
+
97
+ context 'when value is integer' do
98
+ let(:value) { 123 }
99
+ it { errors.must_be_nil }
100
+ end
101
+
102
+ context 'when value is float' do
103
+ let(:value) { 123.4 }
104
+ it { errors.must_equal ["is not a number"]}
105
+ end
106
+
107
+ context 'when value is string' do
108
+ let(:value) { 'abc' }
109
+ it { errors.must_equal ["is not a number"]}
110
+ end
111
+
112
+ context 'when value is nil' do
113
+ let(:value) { nil }
114
+ it { errors.must_equal ["is not a number"]}
115
+ end
116
+
117
+ context 'when value is everything else' do
118
+ let(:value) { ['array'] }
119
+ it { errors.must_equal ["is not a number"]}
120
+ end
121
+ end
122
+
123
+ describe 'length_range' do
124
+ context 'when range is array' do
125
+ let(:options) {{:length_range => [5, 8, 15]}}
126
+
127
+ context 'when value length is in array' do
128
+ let(:value) { 'abcde' }
129
+ it { errors.must_be_nil }
130
+ end
131
+
132
+ context 'when value length is not in array' do
133
+ let(:value) { 'abc' }
134
+ it { errors.must_equal ["is too short or too long"] }
135
+ end
136
+
137
+ context 'when value length is nil' do
138
+ let(:value) { nil }
139
+ it { errors.must_equal ["is too short or too long"] }
140
+ end
141
+ end
142
+
143
+ context 'when range is range' do
144
+ let(:options) {{:length_range => 5..10}}
145
+
146
+ context 'when value length is in range' do
147
+ let(:value) { 'abcdef' }
148
+ it { errors.must_be_nil }
149
+ end
150
+
151
+ context 'when value length is not in range' do
152
+ let(:value) { 'abc' }
153
+ it { errors.must_equal ["is too short or too long"] }
154
+ end
155
+
156
+ context 'when value length is nil' do
157
+ let(:value) { nil }
158
+ it { errors.must_equal ["is too short or too long"] }
159
+ end
160
+ end
161
+ end
162
+
163
+ describe 'max_length' do
164
+ let(:options) {{:max_length => 10}}
165
+
166
+ context 'when value length is less than max' do
167
+ let(:value) { 'abc' }
168
+ it { errors.must_be_nil }
169
+ end
170
+
171
+ context 'when value is too long' do
172
+ let(:value) { 'abcdefghijklmnop' }
173
+ it { errors.must_equal ["is longer than 10 characters"] }
174
+ end
175
+
176
+ context 'when value is nil' do
177
+ let(:value) { nil }
178
+ it { errors.must_equal ["is longer than 10 characters"] }
179
+ end
180
+ end
181
+
182
+ describe 'min_length' do
183
+ let(:options) {{:min_length => 5}}
184
+
185
+ context 'when value length is greater than min' do
186
+ let(:value) { 'abcdefg' }
187
+ it { errors.must_be_nil }
188
+ end
189
+
190
+ context 'when value is too short' do
191
+ let(:value) { 'abcd' }
192
+ it { errors.must_equal ["is shorter than 5 characters"] }
193
+ end
194
+
195
+ context 'when value is nil' do
196
+ let(:value) { nil }
197
+ it { errors.must_equal ["is shorter than 5 characters"] }
198
+ end
199
+ end
200
+
201
+ describe 'not_null' do
202
+ let(:options) {{:not_null => 5}}
203
+
204
+ context 'when value is not null' do
205
+ let(:value) { 123 }
206
+ it { errors.must_be_nil }
207
+ end
208
+
209
+ context 'when value is nil' do
210
+ let(:value) { nil }
211
+ it { errors.must_equal ["is not present"]}
212
+ end
213
+ end
214
+
215
+ describe 'numeric' do
216
+ let(:options) {{:numeric => true}}
217
+
218
+ context 'when value is integer' do
219
+ let(:value) { 123 }
220
+ it { errors.must_be_nil }
221
+ end
222
+
223
+ context 'when value is float' do
224
+ let(:value) { 123.4 }
225
+ it { errors.must_be_nil }
226
+ end
227
+
228
+ context 'when value is string' do
229
+ let(:value) { 'abc' }
230
+ it { errors.must_equal ["is not a number"]}
231
+ end
232
+
233
+ context 'when value is nil' do
234
+ let(:value) { nil }
235
+ it { errors.must_equal ["is not a number"]}
236
+ end
237
+
238
+ context 'when value is everything else' do
239
+ let(:value) { ['array'] }
240
+ it { errors.must_equal ["is not a number"]}
241
+ end
242
+ end
243
+
244
+ describe 'presence' do
245
+ let(:options) {{:presence => true}}
246
+
247
+ context 'when value is not null' do
248
+ let(:value) { 123 }
249
+ it { errors.must_be_nil }
250
+ end
251
+
252
+ context 'when value is nil' do
253
+ let(:value) { nil }
254
+ it { errors.must_equal ["is not present"]}
255
+ end
256
+
257
+ context 'when value is empty string' do
258
+ let(:value) { '' }
259
+ it { errors.must_equal ["is not present"]}
260
+ end
261
+
262
+ context 'when value is string of whitespace' do
263
+ let(:value) { ' ' }
264
+ it { errors.must_equal ["is not present"]}
265
+ end
266
+
267
+ context 'when value is empty array' do
268
+ let(:value) { [] }
269
+ it { errors.must_equal ["is not present"]}
270
+ end
271
+
272
+ context 'when value is empty hash' do
273
+ let(:value) {{}}
274
+ it { errors.must_equal ["is not present"]}
275
+ end
276
+ end
277
+ end
278
+
279
+ describe 'conditions' do
280
+ describe 'with_options' do
281
+ let(:conditions) {{:if => true}}
282
+ let(:validator_class) do
283
+ klass = Class.new{
284
+ include Veto.validator
285
+
286
+ def create_errors
287
+ errors.add(:base, "error")
288
+ end
289
+ }
290
+ klass.with_options conditions do
291
+ validate :create_errors
292
+ end
293
+ klass
294
+ end
295
+
296
+ context 'when conditions pass' do
297
+ let(:conditions) {{:if => true}}
298
+
299
+ it 'performs validations within block' do
300
+ validator.valid?.must_equal false
301
+ validator.errors.full_messages.must_equal ['base error']
302
+ end
303
+ end
304
+
305
+ context 'when conditions fail' do
306
+ let(:conditions) {{:if => false}}
307
+
308
+ it 'does not perform validations within block' do
309
+ validator.valid?
310
+ validator.errors.must_be_empty
311
+ end
312
+ end
313
+ end
314
+
315
+ describe 'validates' do
316
+ let(:entity){ stub(:title => nil, :name => 'John') }
317
+ let(:options) {{}}
318
+ let(:validator_class) do
319
+ klass = Class.new{
320
+ include Veto.validator
321
+ }
322
+
323
+ klass.validates :title, options
324
+ klass
325
+ end
326
+
327
+ context 'when outer conditions pass' do
328
+ context 'when inner conditions pass' do
329
+ let(:options) {{:not_null => {:with => true, :if => true}, :exact_length => {:with => 4, :if => true}, :if => true}}
330
+
331
+ it 'performs validation' do
332
+ validator.valid?.must_equal false
333
+ validator.errors.full_messages.must_equal ["title is not present", "title is not 4 characters"]
334
+ end
335
+ end
336
+
337
+ context 'when inner conditions fail' do
338
+ let(:options) {{:not_null => {:with => true, :if => false}, :exact_length => {:with => 4, :if => true}, :if => true}}
339
+
340
+ it 'skips individual validator' do
341
+ validator.valid?.must_equal false
342
+ validator.errors.full_messages.must_equal ["title is not 4 characters"]
343
+ end
344
+ end
345
+ end
346
+
347
+ context 'when outer conditions fail' do
348
+ let(:options) {{:not_null => {:with => true, :if => true}, :exact_length => {:with => 4, :if => true}, :if => false}}
349
+
350
+ it 'skips validates block' do
351
+ validator.valid?.must_equal true
352
+ end
353
+ end
354
+ end
355
+ end
356
+
357
+ describe 'custom attribute validator class' do
358
+ let(:entity){ stub(:email_address => 'blah') }
359
+ let(:validator_class) do
360
+ klass = Class.new{
361
+ include Veto.validator
362
+
363
+ class EmailValidator < ::Veto::AttributeValidator
364
+ def validate entity, attribute, value, errors, options={}
365
+ unless value.to_s =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
366
+ errors.add(attribute, "is not a valid email address")
367
+ end
368
+ end
369
+ end
370
+
371
+ validates :email_address, :email => true
372
+ }
373
+ end
374
+
375
+ it 'uses custom validator' do
376
+ validator.valid?.must_equal false
377
+ validator.errors.full_messages.must_equal ["email_address is not a valid email address"]
378
+ end
379
+ end
380
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+ require 'veto/validator'
3
+
4
+ describe Veto::Validator do
5
+ let(:entity){ stub }
6
+ let(:validator_class) { Class.new{ include Veto::Validator } }
7
+ let(:validator) { validator_class.new(entity) }
8
+
9
+ describe '::builder' do
10
+ it 'returns builder' do
11
+ validator_class.send(:builder).must_be_instance_of Veto::Builder
12
+ end
13
+ end
14
+
15
+ describe '::with_options' do
16
+ it 'delegates to builder' do
17
+ builder = stub
18
+ validator_class.expects(:builder).returns(builder)
19
+ builder.expects(:with_options).with('args')
20
+ validator_class.with_options('args')
21
+ end
22
+ end
23
+
24
+ describe '::validates' do
25
+ it 'delegates to builder' do
26
+ builder = stub
27
+ validator_class.expects(:builder).returns(builder)
28
+ builder.expects(:validates).with('args')
29
+ validator_class.validates('args')
30
+ end
31
+ end
32
+
33
+ describe '::validate' do
34
+ it 'delegates to builder' do
35
+ builder = stub
36
+ validator_class.expects(:builder).returns(builder)
37
+ builder.expects(:validate).with('args')
38
+ validator_class.validate('args')
39
+ end
40
+ end
41
+
42
+ describe '::validate_with' do
43
+ it 'adds validator to validators array' do
44
+ validator = stub
45
+ validator_class.validate_with validator
46
+ validator_class.validators.must_equal [validator]
47
+ end
48
+
49
+ it 'adds validators to validators array' do
50
+ validator = stub
51
+ validator_class.validate_with [validator, validator]
52
+ validator_class.validators.must_equal [validator, validator]
53
+ end
54
+ end
55
+
56
+ describe '::validators' do
57
+ it 'returns validators list' do
58
+ validator_class.validators.must_equal []
59
+ end
60
+ end
61
+
62
+ describe '::valid?' do
63
+ it 'initializes new instance and delegates to instance method' do
64
+ validator_class.expects(:new).with(entity).returns(entity)
65
+ entity.expects(:valid?)
66
+ validator_class.valid?(entity)
67
+ end
68
+ end
69
+
70
+ describe '::validate!' do
71
+ it 'initializes new instance and delegates to instance method' do
72
+ validator_class.expects(:new).with(entity).returns(entity)
73
+ entity.expects(:validate!)
74
+ validator_class.validate!(entity)
75
+ end
76
+ end
77
+
78
+ describe '#valid?' do
79
+ context 'when entity is valid' do
80
+ it 'returns true' do
81
+ errors = stub(:empty? => true)
82
+ validator.expects(:errors => errors)
83
+ validator.valid?.must_equal true
84
+ end
85
+ end
86
+
87
+ context 'when entity is invalid' do
88
+ it 'returns false' do
89
+ errors = stub(:empty? => false)
90
+ validator.expects(:errors => errors)
91
+ validator.valid?.must_equal false
92
+ end
93
+ end
94
+ end
95
+
96
+ describe '#validate!' do
97
+ context 'when entity is valid' do
98
+ it 'returns true' do
99
+ validator.expects(:valid?).returns(true)
100
+ validator.validate!.must_be_nil
101
+ end
102
+ end
103
+
104
+ context 'when entity is invalid' do
105
+ it 'returns false' do
106
+ errors = stub(:full_messages => '')
107
+ validator.expects(:valid?).returns(false)
108
+ validator.expects(:errors => errors)
109
+ proc { validator.validate! }.must_raise ::Veto::InvalidEntity
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#errors' do
115
+ it 'returns errors object' do
116
+ validator.errors.must_be_instance_of Veto::Errors
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'veto/validators/exact_length_validator'
3
+ require 'veto/errors'
4
+
5
+ describe Veto::ExactLengthValidator do
6
+ let(:errors){ Veto::Errors.new }
7
+ let(:entity) { Object.new }
8
+ let(:attribute) { :title }
9
+ let(:value) { 'blahblah' }
10
+ let(:options) {{:with => 10}}
11
+ let(:validator){ Veto::ExactLengthValidator.new(stub, stub) }
12
+ let(:result){ validator.validate(entity, attribute, value, errors, options) }
13
+
14
+ describe '#validate' do
15
+ before { result }
16
+
17
+ context 'when value exact length' do
18
+ let(:value) { 'abcdefghij' }
19
+ it { errors[:title].must_be_nil }
20
+ end
21
+
22
+ context 'when value is too short' do
23
+ let(:value) { 'short' }
24
+ it { errors[:title].must_equal ["is not 10 characters"] }
25
+ end
26
+
27
+ context 'when value is too long' do
28
+ let(:value) { 'this title is wayyyy to long' }
29
+ it { errors[:title].must_equal ["is not 10 characters"] }
30
+ end
31
+
32
+ context 'when value is nil' do
33
+ let(:value) { nil }
34
+ it { errors[:title].must_equal ["is not 10 characters"] }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'veto/validators/format_validator'
3
+ require 'veto/errors'
4
+
5
+ describe Veto::FormatValidator do
6
+ let(:errors){ Veto::Errors.new }
7
+ let(:entity) { Object.new }
8
+ let(:attribute) { :title }
9
+ let(:value) { 'blahblah' }
10
+ let(:options) {{:with => /^\d+$/}}
11
+ let(:validator){ Veto::FormatValidator.new(stub, stub) }
12
+ let(:result){ validator.validate(entity, attribute, value, errors, options) }
13
+
14
+ describe '#validate' do
15
+ before { result }
16
+
17
+ context 'when value matches pattern' do
18
+ let(:value) { 123 }
19
+ it { errors[:title].must_be_nil }
20
+ end
21
+
22
+ context 'when value does not match' do
23
+ let(:value) { 'abc' }
24
+ it { errors[:title].must_equal ["is not valid"] }
25
+ end
26
+
27
+ context 'when value is nil' do
28
+ let(:value) { nil }
29
+ it { errors[:title].must_equal ["is not valid"] }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'veto/validators/inclusion_validator'
3
+ require 'veto/errors'
4
+
5
+ describe Veto::InclusionValidator do
6
+ let(:errors){ Veto::Errors.new }
7
+ let(:entity) { Object.new }
8
+ let(:attribute) { :title }
9
+ let(:value) { 'blahblah' }
10
+ let(:options) {{:in => %w(cat dog bird rabbit)}}
11
+ let(:validator){ Veto::InclusionValidator.new(stub, stub) }
12
+ let(:result){ validator.validate(entity, attribute, value, errors, options) }
13
+
14
+ describe '#validate' do
15
+ before { result }
16
+
17
+ context 'when set is array' do
18
+ let(:options) {{:in => %w(cat dog bird rabbit)}}
19
+
20
+ context 'when value is in set' do
21
+ let(:value) { 'cat' }
22
+ it { errors[:title].must_be_nil }
23
+ end
24
+
25
+ context 'when value is not in set' do
26
+ let(:value) { 'goat' }
27
+ it { errors[:title].must_equal ["is not in set: [\"cat\", \"dog\", \"bird\", \"rabbit\"]"]}
28
+ end
29
+ end
30
+
31
+ context 'when set is range' do
32
+ let(:options) {{:in => (10..20)}}
33
+
34
+ context 'when value is in set' do
35
+ let(:value) { 11 }
36
+ it { errors[:title].must_be_nil }
37
+ end
38
+
39
+ context 'when value is not in set' do
40
+ let(:value) { 5 }
41
+ it { errors[:title].must_equal ["is not in set: 10..20"] }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'veto/validators/integer_validator'
3
+ require 'veto/errors'
4
+
5
+ describe Veto::IntegerValidator do
6
+ let(:errors){ Veto::Errors.new }
7
+ let(:entity) { Object.new }
8
+ let(:attribute) { :title }
9
+ let(:value) { 'blahblah' }
10
+ let(:options) {{:with => {}}}
11
+ let(:validator){ Veto::IntegerValidator.new(stub, stub) }
12
+ let(:result){ validator.validate(entity, attribute, value, errors, options) }
13
+
14
+ describe '#validate' do
15
+ before { result }
16
+
17
+ context 'when value is integer' do
18
+ let(:value) { 123 }
19
+ it { errors[:title].must_be_nil }
20
+ end
21
+
22
+ context 'when value is float' do
23
+ let(:value) { 123.4 }
24
+ it { errors[:title].must_equal ["is not a number"]}
25
+ end
26
+
27
+ context 'when value is string' do
28
+ let(:value) { 'abc' }
29
+ it { errors[:title].must_equal ["is not a number"]}
30
+ end
31
+
32
+ context 'when value is nil' do
33
+ let(:value) { nil }
34
+ it { errors[:title].must_equal ["is not a number"]}
35
+ end
36
+
37
+ context 'when value is everything else' do
38
+ let(:value) { ['array'] }
39
+ it { errors[:title].must_equal ["is not a number"]}
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'veto/validators/length_range_validator'
3
+ require 'veto/errors'
4
+
5
+ describe Veto::LengthRangeValidator do
6
+ let(:errors){ Veto::Errors.new }
7
+ let(:entity) { Object.new }
8
+ let(:attribute) { :title }
9
+ let(:value) { 'blahblah' }
10
+ let(:options) {{:in => (1..10)}}
11
+ let(:validator){ Veto::LengthRangeValidator.new(attribute, options) }
12
+ let(:result){ validator.validate(entity, attribute, value, errors, options) }
13
+
14
+ describe '#validate' do
15
+ before { result }
16
+
17
+ context 'when range is array' do
18
+ let(:options) {{:in => [5, 8, 15]}}
19
+
20
+ context 'when value length is in array' do
21
+ let(:value) { 'abcde' }
22
+ it { errors[:title].must_be_nil }
23
+ end
24
+
25
+ context 'when value length is not in array' do
26
+ let(:value) { 'abc' }
27
+ it { errors[:title].must_equal ["is too short or too long"] }
28
+ end
29
+
30
+ context 'when value length is nil' do
31
+ let(:value) { nil }
32
+ it { errors[:title].must_equal ["is too short or too long"] }
33
+ end
34
+ end
35
+
36
+ context 'when range is range' do
37
+ let(:options) {{:in => (5..10)}}
38
+
39
+ context 'when value length is in range' do
40
+ let(:value) { 'abcdef' }
41
+ it { errors[:title].must_be_nil }
42
+ end
43
+
44
+ context 'when value length is not in range' do
45
+ let(:value) { 'abc' }
46
+ it { errors[:title].must_equal ["is too short or too long"] }
47
+ end
48
+
49
+ context 'when value length is nil' do
50
+ let(:value) { nil }
51
+ it { errors[:title].must_equal ["is too short or too long"] }
52
+ end
53
+ end
54
+ end
55
+ end