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