duck-hunt 0.0.3

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 (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