duck-hunt 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +526 -0
  3. data/Rakefile +15 -0
  4. data/lib/duck-hunt.rb +17 -0
  5. data/lib/duck-hunt/hash_helpers.rb +28 -0
  6. data/lib/duck-hunt/properties.rb +13 -0
  7. data/lib/duck-hunt/properties/array.rb +81 -0
  8. data/lib/duck-hunt/properties/boolean.rb +10 -0
  9. data/lib/duck-hunt/properties/float.rb +10 -0
  10. data/lib/duck-hunt/properties/integer.rb +9 -0
  11. data/lib/duck-hunt/properties/nested_hash.rb +61 -0
  12. data/lib/duck-hunt/properties/nil.rb +15 -0
  13. data/lib/duck-hunt/properties/property.rb +85 -0
  14. data/lib/duck-hunt/properties/string.rb +10 -0
  15. data/lib/duck-hunt/properties/validator_lookup.rb +27 -0
  16. data/lib/duck-hunt/schemas.rb +8 -0
  17. data/lib/duck-hunt/schemas/array_schema.rb +254 -0
  18. data/lib/duck-hunt/schemas/hash_schema.rb +135 -0
  19. data/lib/duck-hunt/schemas/property_lookup.rb +32 -0
  20. data/lib/duck-hunt/schemas/schema_definition.rb +25 -0
  21. data/lib/duck-hunt/string_helpers.rb +25 -0
  22. data/lib/duck-hunt/validators.rb +16 -0
  23. data/lib/duck-hunt/validators/accepted_values.rb +19 -0
  24. data/lib/duck-hunt/validators/divisible_by.rb +19 -0
  25. data/lib/duck-hunt/validators/equal_to.rb +19 -0
  26. data/lib/duck-hunt/validators/greater_than.rb +19 -0
  27. data/lib/duck-hunt/validators/greater_than_or_equal_to.rb +19 -0
  28. data/lib/duck-hunt/validators/less_than.rb +19 -0
  29. data/lib/duck-hunt/validators/less_than_or_equal_to.rb +19 -0
  30. data/lib/duck-hunt/validators/matches.rb +18 -0
  31. data/lib/duck-hunt/validators/not_divisible_by.rb +19 -0
  32. data/lib/duck-hunt/validators/not_equal_to.rb +19 -0
  33. data/lib/duck-hunt/validators/rejected_values.rb +19 -0
  34. data/lib/duck-hunt/validators/validator.rb +16 -0
  35. data/lib/duck-hunt/version.rb +3 -0
  36. data/test/properties/array_test.rb +837 -0
  37. data/test/properties/boolean_test.rb +37 -0
  38. data/test/properties/float_test.rb +49 -0
  39. data/test/properties/integer_test.rb +48 -0
  40. data/test/properties/nested_hash_test.rb +465 -0
  41. data/test/properties/nil_test.rb +30 -0
  42. data/test/properties/property_test.rb +193 -0
  43. data/test/properties/string_test.rb +24 -0
  44. data/test/properties/validator_lookup_test.rb +25 -0
  45. data/test/schemas/array_schema_test.rb +797 -0
  46. data/test/schemas/hash_schema_test.rb +264 -0
  47. data/test/schemas/property_lookup_test.rb +41 -0
  48. data/test/schemas/schema_definition_test.rb +51 -0
  49. data/test/test_helper.rb +29 -0
  50. data/test/test_helper/test_classes.rb +74 -0
  51. data/test/validators/accepted_values_test.rb +46 -0
  52. data/test/validators/divisible_by_test.rb +38 -0
  53. data/test/validators/equal_to_test.rb +38 -0
  54. data/test/validators/greater_than_or_equal_to_test.rb +39 -0
  55. data/test/validators/greater_than_test.rb +39 -0
  56. data/test/validators/less_than_or_equal_to_test.rb +40 -0
  57. data/test/validators/less_than_test.rb +39 -0
  58. data/test/validators/matches_test.rb +43 -0
  59. data/test/validators/not_divisible_by_test.rb +38 -0
  60. data/test/validators/not_equal_to_test.rb +38 -0
  61. data/test/validators/rejected_values_test.rb +46 -0
  62. data/test/validators/validator_test.rb +23 -0
  63. metadata +196 -0
@@ -0,0 +1,19 @@
1
+ module DuckHunt
2
+ module Validators
3
+ class RejectedValues < Validator
4
+ attr_reader :values
5
+ def initialize(*args)
6
+ @values = args[0]
7
+ raise ArgumentError, "an array must be provided" unless @values.is_a? Array
8
+ end
9
+
10
+ def valid?(value)
11
+ return (@values.include? value) == false
12
+ end
13
+
14
+ def error_message
15
+ return "a rejected value"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module DuckHunt
2
+ module Validators
3
+ class Validator
4
+ def initialize(*args)
5
+ end
6
+
7
+ def valid?(value)
8
+ raise NotImplementedError
9
+ end
10
+
11
+ def error_message
12
+ raise NotImplementedError
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module DuckHunt
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,837 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ describe DuckHunt::Properties::Array, "initialize using a block" do
4
+ it "should be able to set the property to required" do
5
+ property = DuckHunt::Properties::Array.new :required => true do |s|
6
+ s.test
7
+ end
8
+ property.required.must_equal true
9
+ property.required?.must_equal true
10
+ end
11
+
12
+ it "should be able to define a single-type array" do
13
+ property = DuckHunt::Properties::Array.new do |s|
14
+ s.integer
15
+ end
16
+
17
+ property.single_type_property.must_be_instance_of DuckHunt::Properties::Integer
18
+ property.tuple_properties.must_be_nil
19
+ property.optional_tuple_properties.must_be_nil
20
+ end
21
+
22
+ it "should be able to define a tuple array with no optional items" do
23
+ property = DuckHunt::Properties::Array.new do |s|
24
+ s.items do |x|
25
+ x.integer
26
+ end
27
+ end
28
+
29
+ property.tuple_properties.size.must_equal 1
30
+ property.tuple_properties.first.must_be_instance_of DuckHunt::Properties::Integer
31
+
32
+ property = DuckHunt::Properties::Array.new do |s|
33
+ s.items do |x|
34
+ x.integer
35
+ x.test
36
+ end
37
+ end
38
+
39
+ property.tuple_properties.size.must_equal 2
40
+ property.tuple_properties.first.must_be_instance_of DuckHunt::Properties::Integer
41
+ property.tuple_properties.last.must_be_instance_of DuckHunt::Properties::Test
42
+ end
43
+
44
+ it "should be able to define a tuple array with optional items" do
45
+ property = DuckHunt::Properties::Array.new do |s|
46
+ s.items do |x|
47
+ x.integer
48
+ end
49
+
50
+ s.optional_items do |y|
51
+ y.integer
52
+ y.test
53
+ end
54
+ end
55
+
56
+ property.tuple_properties.size.must_equal 1
57
+ property.tuple_properties.first.must_be_instance_of DuckHunt::Properties::Integer
58
+
59
+ property.optional_tuple_properties.size.must_equal 2
60
+ property.optional_tuple_properties.first.must_be_instance_of DuckHunt::Properties::Integer
61
+ property.optional_tuple_properties.last.must_be_instance_of DuckHunt::Properties::Test
62
+
63
+ property = DuckHunt::Properties::Array.new do |s|
64
+ s.items do |x|
65
+ x.integer
66
+ x.test
67
+ end
68
+
69
+ s.optional_items do |x|
70
+ x.integer
71
+ end
72
+ end
73
+
74
+ property.tuple_properties.size.must_equal 2
75
+ property.tuple_properties.first.must_be_instance_of DuckHunt::Properties::Integer
76
+ property.tuple_properties.last.must_be_instance_of DuckHunt::Properties::Test
77
+
78
+ property.optional_tuple_properties.size.must_equal 1
79
+ property.optional_tuple_properties.first.must_be_instance_of DuckHunt::Properties::Integer
80
+ end
81
+
82
+ it "should not allow single-type and tuple definitions in the same property" do
83
+ lambda{
84
+ property = DuckHunt::Properties::Array.new do |s|
85
+ s.integer
86
+ s.items do |x|
87
+ x.integer
88
+ end
89
+ end
90
+ }.must_raise DuckHunt::InvalidSchema
91
+
92
+ lambda{
93
+ property = DuckHunt::Properties::Array.new do |s|
94
+ s.items do |x|
95
+ x.integer
96
+ end
97
+ s.integer
98
+ end
99
+ }.must_raise DuckHunt::InvalidSchema
100
+
101
+ lambda{
102
+ property = DuckHunt::Properties::Array.new do |s|
103
+ s.integer
104
+ s.optional_items do |x|
105
+ x.integer
106
+ end
107
+ end
108
+ }.must_raise DuckHunt::InvalidSchema
109
+
110
+ lambda{
111
+ property = DuckHunt::Properties::Array.new do |s|
112
+ s.optional_items do |x|
113
+ x.integer
114
+ end
115
+ s.integer
116
+ end
117
+ }.must_raise DuckHunt::InvalidSchema
118
+ end
119
+
120
+ it "should be able to set options for the property" do
121
+ property = DuckHunt::Properties::Array.new :min_size => 3 do |s|
122
+ s.test
123
+ end
124
+
125
+ property.min_size.must_equal 3
126
+ end
127
+
128
+ it "should be able to set property-level and property-level options at the same time" do
129
+ property = DuckHunt::Properties::Array.new :required => true, :min_size => 3 do |s|
130
+ s.test
131
+ end
132
+ property.required.must_equal true
133
+ property.required?.must_equal true
134
+ property.min_size.must_equal 3
135
+ end
136
+
137
+ it "should require that a block be passed when setting tuple properties" do
138
+ lambda{
139
+ property = DuckHunt::Properties::Array.new do |s|
140
+ s.items
141
+ end
142
+ }.must_raise ArgumentError
143
+
144
+ lambda{
145
+ property = DuckHunt::Properties::Array.new do |s|
146
+ s.optional_items
147
+ end
148
+ }.must_raise ArgumentError
149
+ end
150
+
151
+ it "should allow the uniqueness flag to be set during initialization" do
152
+ property = DuckHunt::Properties::Array.new :validates_uniqueness => true do |s|
153
+ s.integer
154
+ end
155
+
156
+ property.validates_uniqueness?.must_equal true
157
+ property.validates_uniqueness.must_equal true
158
+ end
159
+
160
+ it "should allow the min and max size to be set during initialization" do
161
+ property = DuckHunt::Properties::Array.new :min_size => 10 do |s|
162
+ s.integer
163
+ end
164
+
165
+ property.min_size.must_equal 10
166
+ property.max_size.must_be_nil
167
+
168
+ property = DuckHunt::Properties::Array.new :max_size => 10 do |s|
169
+ s.integer
170
+ end
171
+
172
+ property.min_size.must_be_nil
173
+ property.max_size.must_equal 10
174
+
175
+ property = DuckHunt::Properties::Array.new :min_size => 5, :max_size => 10 do |s|
176
+ s.integer
177
+ end
178
+
179
+ property.min_size.must_equal 5
180
+ property.max_size.must_equal 10
181
+ end
182
+
183
+ it "should allow the 'allow nil' flag to be set during initialization" do
184
+ property = DuckHunt::Properties::Array.new :allow_nil => true do |s|
185
+ s.integer
186
+ end
187
+
188
+ property.allow_nil.must_equal true
189
+ property.allow_nil?.must_equal true
190
+ end
191
+
192
+ it "should default the uniqueness flag to false" do
193
+ property = DuckHunt::Properties::Array.new do |s|
194
+ s.integer
195
+ end
196
+
197
+ property.validates_uniqueness.must_equal false
198
+ property.validates_uniqueness?.must_equal false
199
+ end
200
+
201
+ it "should default the min and max size to nil" do
202
+ property = DuckHunt::Properties::Array.new do |s|
203
+ s.integer
204
+ end
205
+
206
+ property.min_size.must_be_nil
207
+ property.max_size.must_be_nil
208
+ end
209
+
210
+ it "should default the 'allow nil' flag to false" do
211
+ property = DuckHunt::Properties::Array.new do |s|
212
+ s.integer
213
+ end
214
+
215
+ property.allow_nil.must_equal false
216
+ property.allow_nil?.must_equal false
217
+ end
218
+ end
219
+
220
+ describe DuckHunt::Properties::Array, "initialize without a block" do
221
+ it "should raise an exception if a block is not provided" do
222
+ lambda{
223
+ DuckHunt::Properties::Array.new :required => false
224
+ }.must_raise(ArgumentError)
225
+ end
226
+ end
227
+
228
+ describe DuckHunt::Properties::Array, "single-type validation" do
229
+ before do
230
+ @property = DuckHunt::Properties::Array.new do |s|
231
+ s.integer
232
+ end
233
+ end
234
+
235
+ it "should return false if the object provided is not an array" do
236
+ @property.valid?("hello").must_equal false
237
+ @property.errors.size.must_equal 1
238
+ @property.errors["base"].must_equal ["wrong type"]
239
+ end
240
+
241
+ it "should return true if there are no entries in the array" do
242
+ @property.valid?([]).must_equal true
243
+ @property.errors.size.must_equal 0
244
+ end
245
+
246
+ it "should return true if every entry in the array is of the correct type" do
247
+ @property.valid?([1,2,3]).must_equal true
248
+ @property.errors.size.must_equal 0
249
+ end
250
+
251
+ it "should return false if any entry in the array is not of the correct type, and have a base error mesage" do
252
+ @property.valid?([1,"boo",3]).must_equal false
253
+ @property.errors.size.must_equal 1
254
+ @property.errors["1"].must_equal ["wrong type"]
255
+ end
256
+
257
+ it "should empty the errors array each time we validate" do
258
+ @property.valid?([1,"boo",3]).must_equal false
259
+ @property.errors.size.must_equal 1
260
+ @property.errors["1"].must_equal ["wrong type"]
261
+
262
+ @property.valid?(["boo",2,3]).must_equal false
263
+ @property.errors.size.must_equal 1
264
+ @property.errors["0"].must_equal ["wrong type"]
265
+ end
266
+ end
267
+
268
+ describe DuckHunt::Properties::Array, "tuple validation (no optional items)" do
269
+ before do
270
+ @property = DuckHunt::Properties::Array.new do |s|
271
+ s.items do |x|
272
+ x.always_right_type
273
+ x.integer
274
+ end
275
+ end
276
+ end
277
+
278
+ it "should return false if the object provided is not an array" do
279
+ @property.valid?("hello").must_equal false
280
+ @property.errors.size.must_equal 1
281
+ @property.errors["base"].must_equal ["wrong type"]
282
+ end
283
+
284
+ it "should return false if there are no items in the array" do
285
+ @property.valid?([]).must_equal false
286
+ @property.errors.size.must_equal 1
287
+ @property.errors["base"].must_equal ["expected at least 2 item(s) but got 0 item(s)"]
288
+ end
289
+
290
+ it "should return false if there are fewer items in the array than what is defined in the tuple" do
291
+ @property.valid?([1]).must_equal false
292
+ @property.errors.size.must_equal 1
293
+ @property.errors["base"].must_equal ["expected at least 2 item(s) but got 1 item(s)"]
294
+ end
295
+
296
+ it "should return false if there are more items in the array than what is defined in the tuple" do
297
+ @property.valid?([1,2,3]).must_equal false
298
+ @property.errors.size.must_equal 1
299
+ @property.errors["base"].must_equal ["expected at most 2 item(s) but got 3 item(s)"]
300
+ end
301
+
302
+ it "should return false if any of the items are not the correct type specified for that index" do
303
+ @property.valid?([1, "hello"]).must_equal false
304
+ @property.errors.size.must_equal 1
305
+ @property.errors["1"].must_equal ["wrong type"]
306
+ end
307
+
308
+ it "should return true if the items in the array match their defined type" do
309
+ @property.valid?([1, 2]).must_equal true
310
+ @property.errors.size.must_equal 0
311
+ end
312
+
313
+ it "should empty the errors array each time we validate" do
314
+ @property.valid?([1, "hello"]).must_equal false
315
+ @property.errors.size.must_equal 1
316
+ @property.errors["1"].must_equal ["wrong type"]
317
+
318
+ @property.valid?([1]).must_equal false
319
+ @property.errors.size.must_equal 1
320
+ @property.errors["base"].must_equal ["expected at least 2 item(s) but got 1 item(s)"]
321
+ end
322
+ end
323
+
324
+ describe DuckHunt::Properties::Array, "tuple validation (with optional items)" do
325
+ before do
326
+ @property = DuckHunt::Properties::Array.new do |s|
327
+ s.items do |x|
328
+ x.always_right_type
329
+ x.integer
330
+ end
331
+
332
+ s.optional_items do |y|
333
+ y.integer
334
+ y.always_right_type
335
+ end
336
+ end
337
+ end
338
+
339
+ it "should return false if there are no items in the array" do
340
+ @property.valid?([]).must_equal false
341
+ @property.errors.size.must_equal 1
342
+ @property.errors["base"].must_equal ["expected at least 2 item(s) but got 0 item(s)"]
343
+ end
344
+
345
+ it "should return false if there are fewer items in the array than what is defined in the tuple" do
346
+ @property.valid?([1]).must_equal false
347
+ @property.errors.size.must_equal 1
348
+ @property.errors["base"].must_equal ["expected at least 2 item(s) but got 1 item(s)"]
349
+ end
350
+
351
+ it "should return true if we have extended beyond the required tuple items and into the optional items" do
352
+ @property.valid?([1,2,3,4]).must_equal true
353
+ @property.errors.size.must_equal 0
354
+ end
355
+
356
+ it "should return false if there are more items in the array than what is defined in the tuple (including the optional items)" do
357
+ @property.valid?([1,2,3,4,5]).must_equal false
358
+ @property.errors.size.must_equal 1
359
+ @property.errors["base"].must_equal ["expected at most 4 item(s) but got 5 item(s)"]
360
+ end
361
+
362
+ it "should return false if any of the required items are not the correct type specified for that index" do
363
+ @property.valid?([1, "hello"]).must_equal false
364
+ @property.errors.size.must_equal 1
365
+ @property.errors["1"].must_equal ["wrong type"]
366
+ end
367
+
368
+ it "should return false if any of the optional items are not the correct type specified for that index" do
369
+ @property.valid?([1,2,"hello"]).must_equal false
370
+ @property.errors.size.must_equal 1
371
+ @property.errors["2"].must_equal ["wrong type"]
372
+ end
373
+
374
+ it "should return true if the items in the array match their defined type" do
375
+ @property.valid?([1,2,3,4]).must_equal true
376
+ @property.errors.size.must_equal 0
377
+ end
378
+
379
+ it "should return true if we only have the required items in the array" do
380
+ @property.valid?([1,2]).must_equal true
381
+ @property.errors.size.must_equal 0
382
+ end
383
+
384
+ it "should return true if we only have some of the optional items in the array" do
385
+ @property.valid?([1,2,3]).must_equal true
386
+ @property.errors.size.must_equal 0
387
+ end
388
+
389
+ it "should empty the errors array each time we validate" do
390
+ @property.valid?([1, "hello"]).must_equal false
391
+ @property.errors.size.must_equal 1
392
+ @property.errors["1"].must_equal ["wrong type"]
393
+
394
+ @property.valid?([1]).must_equal false
395
+ @property.errors.size.must_equal 1
396
+ @property.errors["base"].must_equal ["expected at least 2 item(s) but got 1 item(s)"]
397
+
398
+ @property.valid?([1,2,"hello"]).must_equal false
399
+ @property.errors.size.must_equal 1
400
+ @property.errors["2"].must_equal ["wrong type"]
401
+ end
402
+ end
403
+
404
+ describe DuckHunt::Properties::Array, "tuple validation (all optional items)" do
405
+ before do
406
+ @property = DuckHunt::Properties::Array.new do |s|
407
+ s.optional_items do |y|
408
+ y.integer
409
+ y.always_right_type
410
+ end
411
+ end
412
+ end
413
+
414
+ it "should return true if there are no items in the array" do
415
+ @property.valid?([]).must_equal true
416
+ @property.errors.size.must_equal 0
417
+ end
418
+
419
+ it "should return true if there are fewer items in the array than what is defined in the tuple" do
420
+ @property.valid?([1]).must_equal true
421
+ @property.errors.size.must_equal 0
422
+ end
423
+
424
+ it "should return false if there are more items in the array than what is defined in the tuple" do
425
+ @property.valid?([1,2,3]).must_equal false
426
+ @property.errors.size.must_equal 1
427
+ @property.errors["base"].must_equal ["expected at most 2 item(s) but got 3 item(s)"]
428
+ end
429
+
430
+ it "should return false if any of the items are not the correct type specified for that index" do
431
+ @property.valid?(["hello",2]).must_equal false
432
+ @property.errors.size.must_equal 1
433
+ @property.errors["0"].must_equal ["wrong type"]
434
+ end
435
+
436
+ it "should return true if the items in the array match their defined type" do
437
+ @property.valid?([1,2]).must_equal true
438
+ @property.errors.size.must_equal 0
439
+ end
440
+
441
+ it "should return true if we only have some of the optional items in the array" do
442
+ @property.valid?([1]).must_equal true
443
+ @property.errors.size.must_equal 0
444
+ end
445
+
446
+ it "should empty the errors array each time we validate" do
447
+ @property.valid?(["hello",2]).must_equal false
448
+ @property.errors.size.must_equal 1
449
+ @property.errors["0"].must_equal ["wrong type"]
450
+
451
+ @property.valid?([1,2,3]).must_equal false
452
+ @property.errors.size.must_equal 1
453
+ @property.errors["base"].must_equal ["expected at most 2 item(s) but got 3 item(s)"]
454
+ end
455
+ end
456
+
457
+ describe DuckHunt::Properties::Array, "validating uniqueness" do
458
+ it "should return false if there were duplicates in a single-type array" do
459
+ property = DuckHunt::Properties::Array.new :validates_uniqueness => true do |s|
460
+ s.integer
461
+ end
462
+
463
+ property.valid?([1,2,1]).must_equal false
464
+ property.errors.size.must_equal 1
465
+ property.errors["base"].must_equal ["duplicate items are not allowed"]
466
+ end
467
+
468
+ it "should return false if there were duplicates in a tuple array (no optional items)" do
469
+ property = DuckHunt::Properties::Array.new :validates_uniqueness => true do |s|
470
+ s.items do |x|
471
+ x.integer
472
+ x.integer
473
+ x.integer
474
+ end
475
+ end
476
+
477
+ property.valid?([1,2,1]).must_equal false
478
+ property.errors.size.must_equal 1
479
+ property.errors["base"].must_equal ["duplicate items are not allowed"]
480
+ end
481
+
482
+ it "should return false if there were duplicates in a tuple array (with optional items)" do
483
+ property = DuckHunt::Properties::Array.new :validates_uniqueness => true do |s|
484
+ s.items do |x|
485
+ x.integer
486
+ x.integer
487
+ end
488
+
489
+ s.optional_items do |x|
490
+ x.integer
491
+ end
492
+ end
493
+
494
+ property.valid?([1,2,1]).must_equal false
495
+ property.errors.size.must_equal 1
496
+ property.errors["base"].must_equal ["duplicate items are not allowed"]
497
+ end
498
+
499
+ it "should return false if there were duplicates in a tuple array (all optional items)" do
500
+ property = DuckHunt::Properties::Array.new :validates_uniqueness => true do |s|
501
+ s.optional_items do |x|
502
+ x.integer
503
+ x.integer
504
+ x.integer
505
+ end
506
+ end
507
+
508
+ property.valid?([1,2,1]).must_equal false
509
+ property.errors.size.must_equal 1
510
+ property.errors["base"].must_equal ["duplicate items are not allowed"]
511
+ end
512
+ end
513
+
514
+ describe DuckHunt::Properties::Array, "validating minimum size" do
515
+ it "should return false if there were not enough items in a single-type array" do
516
+ property = DuckHunt::Properties::Array.new :min_size => 3 do |s|
517
+ s.integer
518
+ end
519
+
520
+ property.valid?([1,2]).must_equal false
521
+ property.errors.size.must_equal 1
522
+ property.errors["base"].must_equal ["expected at least 3 item(s) but got 2 item(s)"]
523
+ end
524
+
525
+ it "should return true if there were just enough items in a single-type array" do
526
+ property = DuckHunt::Properties::Array.new :min_size => 3 do |s|
527
+ s.integer
528
+ end
529
+
530
+ property.valid?([1,2,3]).must_equal true
531
+ property.errors.size.must_equal 0
532
+ end
533
+
534
+ it "should return true if there were more than enough items in a single-type array" do
535
+ property = DuckHunt::Properties::Array.new :min_size => 3 do |s|
536
+ s.integer
537
+ end
538
+
539
+ property.valid?([1,2,3,4]).must_equal true
540
+ property.errors.size.must_equal 0
541
+ end
542
+ end
543
+
544
+ describe DuckHunt::Properties::Array, "validating maximum size" do
545
+ it "should return false if there were too many items in a single-type array" do
546
+ property = DuckHunt::Properties::Array.new :max_size => 3 do |s|
547
+ s.integer
548
+ end
549
+
550
+ property.valid?([1,2,3,4]).must_equal false
551
+ property.errors.size.must_equal 1
552
+ property.errors["base"].must_equal ["expected at most 3 item(s) but got 4 item(s)"]
553
+ end
554
+
555
+ it "should return true if we were at the limit of items in a single-type array" do
556
+ property = DuckHunt::Properties::Array.new :max_size => 3 do |s|
557
+ s.integer
558
+ end
559
+
560
+ property.valid?([1,2,3]).must_equal true
561
+ property.errors.size.must_equal 0
562
+ end
563
+
564
+ it "should return true if we were not close to the limit in a single-type array" do
565
+ property = DuckHunt::Properties::Array.new :max_size => 3 do |s|
566
+ s.integer
567
+ end
568
+
569
+ property.valid?([1]).must_equal true
570
+ property.errors.size.must_equal 0
571
+ end
572
+ end
573
+
574
+ describe DuckHunt::Properties::Array, "validating minimum and maximum size" do
575
+ before do
576
+ @property = DuckHunt::Properties::Array.new :min_size => 3, :max_size => 5 do |s|
577
+ s.integer
578
+ end
579
+ end
580
+
581
+ it "should return false if it is below the minimum" do
582
+ @property.valid?([1,2]).must_equal false
583
+ @property.errors.size.must_equal 1
584
+ @property.errors["base"].must_equal ["expected at least 3 item(s) but got 2 item(s)"]
585
+ end
586
+
587
+ it "should return false if it is above the maximum" do
588
+ @property.valid?([1,2,3,4,5,6]).must_equal false
589
+ @property.errors.size.must_equal 1
590
+ @property.errors["base"].must_equal ["expected at most 5 item(s) but got 6 item(s)"]
591
+ end
592
+
593
+ it "should return true if it is at the minimum" do
594
+ @property.valid?([1,2,3]).must_equal true
595
+ @property.errors.size.must_equal 0
596
+ end
597
+
598
+ it "should return true if it is at the maximum" do
599
+ @property.valid?([1,2,3,4,5]).must_equal true
600
+ @property.errors.size.must_equal 0
601
+ end
602
+
603
+ it "should return true if it is within the range" do
604
+ @property.valid?([1,2,3,4]).must_equal true
605
+ @property.errors.size.must_equal 0
606
+ end
607
+
608
+ it "should return true if the min and max are the same value" do
609
+ property = DuckHunt::Properties::Array.new :min_size => 3, :max_size => 3 do |s|
610
+ s.integer
611
+ end
612
+ property.valid?([1,2,3]).must_equal true
613
+ property.errors.size.must_equal 0
614
+ end
615
+ end
616
+
617
+ describe DuckHunt::Properties::Array, "validating `allow nil`" do
618
+ it "should return false if nil is not allowed and a nil object is given" do
619
+ property = DuckHunt::Properties::Array.new :allow_nil => false do |s|
620
+ s.integer
621
+ end
622
+ property.valid?(nil).must_equal false
623
+ property.errors.size.must_equal 1
624
+ property.errors["base"].must_equal ["nil object not allowed"]
625
+ end
626
+
627
+ it "should return true if nil is allowed and a nil object is given" do
628
+ property = DuckHunt::Properties::Array.new :allow_nil => true do |s|
629
+ s.integer
630
+ end
631
+ property.valid?(nil).must_equal true
632
+ property.errors.size.must_equal 0
633
+ end
634
+ end
635
+
636
+ describe DuckHunt::Properties::Array, "Nesting in single-type array schemas" do
637
+ before do
638
+ @schema = DuckHunt::Schemas::ArraySchema.define do |s|
639
+ s.array do |s|
640
+ s.integer
641
+ end
642
+ end
643
+ end
644
+
645
+ it "should be able to be nested in an array schema" do
646
+ @schema.single_type_property.must_be_instance_of DuckHunt::Properties::Array
647
+ end
648
+
649
+ it "should return true if the nested arrays are valid" do
650
+ @schema.validate?([[1,2,3], [4,5,6]]).must_equal true
651
+ @schema.errors.size.must_equal 0
652
+ end
653
+
654
+ it "should return false if one of the nested arrays is invalid" do
655
+ @schema.validate?([[1,2,3], [4,"herp",6]]).must_equal false
656
+ @schema.errors.size.must_equal 1
657
+ @schema.errors["1"].must_equal({"1" => ["wrong type"]})
658
+ end
659
+
660
+ it "should return false if both of the nested arrays are invalid" do
661
+ @schema.validate?([{}, {}]).must_equal false
662
+ @schema.errors.size.must_equal 2
663
+ @schema.errors["0"].must_equal({"base" => ["wrong type"]})
664
+ @schema.errors["1"].must_equal({"base" => ["wrong type"]})
665
+ end
666
+ end
667
+
668
+ describe DuckHunt::Properties::Array, "Nesting in tuple array schemas (no optional properties)" do
669
+ before do
670
+ @schema = DuckHunt::Schemas::ArraySchema.define do |s|
671
+ s.items do |x|
672
+ x.array do |z|
673
+ z.integer
674
+ end
675
+
676
+ x.array do |y|
677
+ y.integer
678
+ end
679
+ end
680
+ end
681
+ end
682
+
683
+ it "should be able to be nested in an array schema" do
684
+ @schema.tuple_properties.each{|x| x.must_be_instance_of DuckHunt::Properties::Array}
685
+ end
686
+
687
+ it "should return true if the nested arrays are valid" do
688
+ @schema.validate?([[1,2,3], [4,5,6]]).must_equal true
689
+ @schema.errors.size.must_equal 0
690
+ end
691
+
692
+ it "should return false if one of the nested arrays is invalid" do
693
+ @schema.validate?([[1,2,3], [4,"herp",6]]).must_equal false
694
+ @schema.errors.size.must_equal 1
695
+ @schema.errors["1"].must_equal({"1" => ["wrong type"]})
696
+ end
697
+
698
+ it "should return false if both of the nested arrays are invalid" do
699
+ @schema.validate?([{}, {}]).must_equal false
700
+ @schema.errors.size.must_equal 2
701
+ @schema.errors["0"].must_equal({"base" => ["wrong type"]})
702
+ @schema.errors["1"].must_equal({"base" => ["wrong type"]})
703
+ end
704
+ end
705
+
706
+ describe DuckHunt::Properties::Array, "Nesting in tuple array schemas (with optional properties)" do
707
+ before do
708
+ @schema = DuckHunt::Schemas::ArraySchema.define do |s|
709
+ s.items do |x|
710
+ x.array do |z|
711
+ z.integer
712
+ end
713
+ end
714
+
715
+ s.optional_items do |w|
716
+ w.array do |y|
717
+ y.integer
718
+ end
719
+ end
720
+ end
721
+ end
722
+
723
+ it "should be able to be nested in an array schema" do
724
+ @schema.tuple_properties.each{|x| x.must_be_instance_of DuckHunt::Properties::Array}
725
+ @schema.optional_tuple_properties.each{|x| x.must_be_instance_of DuckHunt::Properties::Array}
726
+ end
727
+
728
+ it "should return true if the nested arrays are valid" do
729
+ @schema.validate?([[1,2,3], [4,5,6]]).must_equal true
730
+ @schema.errors.size.must_equal 0
731
+ end
732
+
733
+ it "should return true if only the required arrays are provided" do
734
+ @schema.validate?([[1,2,3]]).must_equal true
735
+ @schema.errors.size.must_equal 0
736
+ end
737
+
738
+ it "should return false if one of the nested arrays is invalid" do
739
+ @schema.validate?([[1,2,3], [4,"herp",6]]).must_equal false
740
+ @schema.errors.size.must_equal 1
741
+ @schema.errors["1"].must_equal({"1" => ["wrong type"]})
742
+
743
+ @schema.validate?([[1,"herp",3], [4,5,6]]).must_equal false
744
+ @schema.errors.size.must_equal 1
745
+ @schema.errors["0"].must_equal({"1" => ["wrong type"]})
746
+ end
747
+
748
+ it "should return false if both of the nested arrays are invalid" do
749
+ @schema.validate?([{}, {}]).must_equal false
750
+ @schema.errors.size.must_equal 2
751
+ @schema.errors["0"].must_equal({"base" => ["wrong type"]})
752
+ @schema.errors["1"].must_equal({"base" => ["wrong type"]})
753
+ end
754
+ end
755
+
756
+ describe DuckHunt::Properties::Array, "Nesting in tuple array schemas (all optional properties)" do
757
+ before do
758
+ @schema = DuckHunt::Schemas::ArraySchema.define do |s|
759
+ s.optional_items do |x|
760
+ x.array do |z|
761
+ z.integer
762
+ end
763
+
764
+ x.array do |w|
765
+ w.integer
766
+ end
767
+ end
768
+ end
769
+ end
770
+
771
+ it "should be able to be nested in an array schema" do
772
+ @schema.optional_tuple_properties.each{|x| x.must_be_instance_of DuckHunt::Properties::Array}
773
+ end
774
+
775
+ it "should return true if the nested arrays are valid" do
776
+ @schema.validate?([[1,2,3], [4,5,6]]).must_equal true
777
+ @schema.errors.size.must_equal 0
778
+ end
779
+
780
+ it "should return true if no arrays are provided" do
781
+ @schema.validate?([]).must_equal true
782
+ @schema.errors.size.must_equal 0
783
+ end
784
+
785
+ it "should return false if one of the nested arrays is invalid" do
786
+ @schema.validate?([[1,2,3], [4,"herp",6]]).must_equal false
787
+ @schema.errors.size.must_equal 1
788
+ @schema.errors["1"].must_equal({"1" => ["wrong type"]})
789
+ end
790
+
791
+ it "should return false if both of the nested arrays are invalid" do
792
+ @schema.validate?([{}, {}]).must_equal false
793
+ @schema.errors.size.must_equal 2
794
+ @schema.errors["0"].must_equal({"base" => ["wrong type"]})
795
+ @schema.errors["1"].must_equal({"base" => ["wrong type"]})
796
+ end
797
+ end
798
+
799
+ describe DuckHunt::Properties::Array, "Nesting in hash" do
800
+ before do
801
+ @schema = DuckHunt::Schemas::HashSchema.define do |s|
802
+ s.array "profile" do |x|
803
+ x.integer
804
+ end
805
+
806
+ s.array "info" do |x|
807
+ x.integer
808
+ end
809
+ end
810
+ end
811
+
812
+ it "should be able to be nested in a hash schema" do
813
+ @schema.properties["profile"].must_be_instance_of DuckHunt::Properties::Array
814
+ end
815
+
816
+ it "should return true if the nested arrays are valid" do
817
+ @schema.validate?({:profile => [1,2,3], :info => [4,5,6]}).must_equal true
818
+ @schema.errors.size.must_equal 0
819
+ end
820
+
821
+ it "should return false if one of the nested arrays is invalid" do
822
+ @schema.validate?({:profile => [1,2,3], :info => {:birthdate => 35}}).must_equal false
823
+ @schema.errors.size.must_equal 1
824
+ @schema.errors["info"].must_equal({"base" => ["wrong type"]})
825
+
826
+ @schema.validate?({:profile => {:name => "John"}, :info => [4,5,6]}).must_equal false
827
+ @schema.errors.size.must_equal 1
828
+ @schema.errors["profile"].must_equal({"base" => ["wrong type"]})
829
+ end
830
+
831
+ it "should return false if both of the nested arrays are invalid" do
832
+ @schema.validate?({:profile => {}, :info => {}}).must_equal false
833
+ @schema.errors.size.must_equal 2
834
+ @schema.errors["profile"].must_equal({"base" => ["wrong type"]})
835
+ @schema.errors["info"].must_equal({"base" => ["wrong type"]})
836
+ end
837
+ end