schemacop 2.4.7 → 3.0.0.rc0

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +25 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +8 -0
  6. data/README.md +41 -708
  7. data/README_V2.md +775 -0
  8. data/README_V3.md +683 -0
  9. data/Rakefile +8 -12
  10. data/VERSION +1 -1
  11. data/lib/schemacop.rb +35 -37
  12. data/lib/schemacop/base_schema.rb +37 -0
  13. data/lib/schemacop/railtie.rb +10 -0
  14. data/lib/schemacop/schema.rb +1 -60
  15. data/lib/schemacop/schema2.rb +22 -0
  16. data/lib/schemacop/schema3.rb +21 -0
  17. data/lib/schemacop/scoped_env.rb +25 -13
  18. data/lib/schemacop/v2.rb +26 -0
  19. data/lib/schemacop/{caster.rb → v2/caster.rb} +16 -2
  20. data/lib/schemacop/{collector.rb → v2/collector.rb} +5 -2
  21. data/lib/schemacop/{dupper.rb → v2/dupper.rb} +1 -1
  22. data/lib/schemacop/{field_node.rb → v2/field_node.rb} +4 -3
  23. data/lib/schemacop/v2/node.rb +142 -0
  24. data/lib/schemacop/{node_resolver.rb → v2/node_resolver.rb} +1 -1
  25. data/lib/schemacop/{node_supporting_field.rb → v2/node_supporting_field.rb} +8 -10
  26. data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +6 -3
  27. data/lib/schemacop/{node_with_block.rb → v2/node_with_block.rb} +3 -2
  28. data/lib/schemacop/v2/root_node.rb +6 -0
  29. data/lib/schemacop/v2/validator/array_validator.rb +32 -0
  30. data/lib/schemacop/{validator → v2/validator}/boolean_validator.rb +1 -1
  31. data/lib/schemacop/v2/validator/float_validator.rb +7 -0
  32. data/lib/schemacop/v2/validator/hash_validator.rb +37 -0
  33. data/lib/schemacop/v2/validator/integer_validator.rb +7 -0
  34. data/lib/schemacop/{validator → v2/validator}/nil_validator.rb +1 -1
  35. data/lib/schemacop/v2/validator/number_validator.rb +21 -0
  36. data/lib/schemacop/v2/validator/object_validator.rb +29 -0
  37. data/lib/schemacop/v2/validator/string_validator.rb +39 -0
  38. data/lib/schemacop/{validator → v2/validator}/symbol_validator.rb +1 -1
  39. data/lib/schemacop/v3.rb +45 -0
  40. data/lib/schemacop/v3/all_of_node.rb +27 -0
  41. data/lib/schemacop/v3/any_of_node.rb +28 -0
  42. data/lib/schemacop/v3/array_node.rb +219 -0
  43. data/lib/schemacop/v3/boolean_node.rb +16 -0
  44. data/lib/schemacop/v3/combination_node.rb +45 -0
  45. data/lib/schemacop/v3/context.rb +17 -0
  46. data/lib/schemacop/v3/dsl_scope.rb +46 -0
  47. data/lib/schemacop/v3/global_context.rb +114 -0
  48. data/lib/schemacop/v3/hash_node.rb +217 -0
  49. data/lib/schemacop/v3/integer_node.rb +13 -0
  50. data/lib/schemacop/v3/is_not_node.rb +32 -0
  51. data/lib/schemacop/v3/node.rb +214 -0
  52. data/lib/schemacop/v3/node_registry.rb +49 -0
  53. data/lib/schemacop/v3/number_node.rb +18 -0
  54. data/lib/schemacop/v3/numeric_node.rb +76 -0
  55. data/lib/schemacop/v3/object_node.rb +40 -0
  56. data/lib/schemacop/v3/one_of_node.rb +28 -0
  57. data/lib/schemacop/v3/reference_node.rb +49 -0
  58. data/lib/schemacop/v3/result.rb +58 -0
  59. data/lib/schemacop/v3/string_node.rb +124 -0
  60. data/lib/schemacop/v3/symbol_node.rb +13 -0
  61. data/schemacop.gemspec +24 -27
  62. data/test/lib/test_helper.rb +152 -0
  63. data/test/schemas/nested/group.rb +6 -0
  64. data/test/schemas/user.rb +7 -0
  65. data/test/unit/schemacop/v2/casting_test.rb +120 -0
  66. data/test/unit/schemacop/v2/collector_test.rb +47 -0
  67. data/test/unit/schemacop/v2/custom_check_test.rb +95 -0
  68. data/test/unit/schemacop/v2/custom_if_test.rb +97 -0
  69. data/test/unit/schemacop/v2/defaults_test.rb +95 -0
  70. data/test/unit/schemacop/v2/empty_test.rb +16 -0
  71. data/test/unit/schemacop/v2/nil_dis_allow_test.rb +43 -0
  72. data/test/unit/schemacop/v2/node_resolver_test.rb +28 -0
  73. data/test/unit/schemacop/v2/short_forms_test.rb +351 -0
  74. data/test/unit/schemacop/v2/types_test.rb +88 -0
  75. data/test/unit/schemacop/v2/validator_array_test.rb +99 -0
  76. data/test/unit/schemacop/v2/validator_boolean_test.rb +17 -0
  77. data/test/unit/schemacop/v2/validator_float_test.rb +59 -0
  78. data/test/unit/schemacop/v2/validator_hash_test.rb +95 -0
  79. data/test/unit/schemacop/v2/validator_integer_test.rb +48 -0
  80. data/test/unit/schemacop/v2/validator_nil_test.rb +15 -0
  81. data/test/unit/schemacop/v2/validator_number_test.rb +62 -0
  82. data/test/unit/schemacop/v2/validator_object_test.rb +141 -0
  83. data/test/unit/schemacop/v2/validator_string_test.rb +78 -0
  84. data/test/unit/schemacop/v2/validator_symbol_test.rb +18 -0
  85. data/test/unit/schemacop/v3/all_of_node_test.rb +199 -0
  86. data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
  87. data/test/unit/schemacop/v3/array_node_test.rb +805 -0
  88. data/test/unit/schemacop/v3/boolean_node_test.rb +126 -0
  89. data/test/unit/schemacop/v3/global_context_test.rb +164 -0
  90. data/test/unit/schemacop/v3/hash_node_test.rb +775 -0
  91. data/test/unit/schemacop/v3/integer_node_test.rb +323 -0
  92. data/test/unit/schemacop/v3/is_not_node_test.rb +173 -0
  93. data/test/unit/schemacop/v3/node_test.rb +148 -0
  94. data/test/unit/schemacop/v3/number_node_test.rb +292 -0
  95. data/test/unit/schemacop/v3/object_node_test.rb +170 -0
  96. data/test/unit/schemacop/v3/one_of_node_test.rb +187 -0
  97. data/test/unit/schemacop/v3/reference_node_test.rb +351 -0
  98. data/test/unit/schemacop/v3/string_node_test.rb +334 -0
  99. data/test/unit/schemacop/v3/symbol_node_test.rb +75 -0
  100. metadata +152 -145
  101. data/doc/Schemacop.html +0 -146
  102. data/doc/Schemacop/ArrayValidator.html +0 -329
  103. data/doc/Schemacop/BooleanValidator.html +0 -145
  104. data/doc/Schemacop/Caster.html +0 -379
  105. data/doc/Schemacop/Collector.html +0 -787
  106. data/doc/Schemacop/Dupper.html +0 -214
  107. data/doc/Schemacop/Exceptions.html +0 -115
  108. data/doc/Schemacop/Exceptions/InvalidSchemaError.html +0 -124
  109. data/doc/Schemacop/Exceptions/ValidationError.html +0 -124
  110. data/doc/Schemacop/FieldNode.html +0 -421
  111. data/doc/Schemacop/FloatValidator.html +0 -158
  112. data/doc/Schemacop/HashValidator.html +0 -293
  113. data/doc/Schemacop/IntegerValidator.html +0 -158
  114. data/doc/Schemacop/NilValidator.html +0 -145
  115. data/doc/Schemacop/Node.html +0 -1438
  116. data/doc/Schemacop/NodeResolver.html +0 -258
  117. data/doc/Schemacop/NodeSupportingField.html +0 -590
  118. data/doc/Schemacop/NodeSupportingType.html +0 -612
  119. data/doc/Schemacop/NodeWithBlock.html +0 -289
  120. data/doc/Schemacop/NumberValidator.html +0 -232
  121. data/doc/Schemacop/ObjectValidator.html +0 -298
  122. data/doc/Schemacop/RootNode.html +0 -171
  123. data/doc/Schemacop/Schema.html +0 -699
  124. data/doc/Schemacop/StringValidator.html +0 -295
  125. data/doc/Schemacop/SymbolValidator.html +0 -145
  126. data/doc/ScopedEnv.html +0 -351
  127. data/doc/_index.html +0 -379
  128. data/doc/class_list.html +0 -51
  129. data/doc/css/common.css +0 -1
  130. data/doc/css/full_list.css +0 -58
  131. data/doc/css/style.css +0 -496
  132. data/doc/file.README.html +0 -833
  133. data/doc/file_list.html +0 -56
  134. data/doc/frames.html +0 -17
  135. data/doc/index.html +0 -833
  136. data/doc/inheritance.graphml +0 -524
  137. data/doc/inheritance.pdf +0 -825
  138. data/doc/js/app.js +0 -303
  139. data/doc/js/full_list.js +0 -216
  140. data/doc/js/jquery.js +0 -4
  141. data/doc/method_list.html +0 -587
  142. data/doc/top-level-namespace.html +0 -112
  143. data/lib/schemacop/node.rb +0 -139
  144. data/lib/schemacop/root_node.rb +0 -4
  145. data/lib/schemacop/validator/array_validator.rb +0 -30
  146. data/lib/schemacop/validator/float_validator.rb +0 -5
  147. data/lib/schemacop/validator/hash_validator.rb +0 -35
  148. data/lib/schemacop/validator/integer_validator.rb +0 -5
  149. data/lib/schemacop/validator/number_validator.rb +0 -19
  150. data/lib/schemacop/validator/object_validator.rb +0 -27
  151. data/lib/schemacop/validator/string_validator.rb +0 -37
  152. data/test/casting_test.rb +0 -118
  153. data/test/collector_test.rb +0 -45
  154. data/test/custom_check_test.rb +0 -93
  155. data/test/custom_if_test.rb +0 -95
  156. data/test/defaults_test.rb +0 -93
  157. data/test/empty_test.rb +0 -14
  158. data/test/nil_dis_allow_test.rb +0 -41
  159. data/test/node_resolver_test.rb +0 -26
  160. data/test/short_forms_test.rb +0 -349
  161. data/test/test_helper.rb +0 -13
  162. data/test/types_test.rb +0 -84
  163. data/test/validator_array_test.rb +0 -97
  164. data/test/validator_boolean_test.rb +0 -15
  165. data/test/validator_float_test.rb +0 -57
  166. data/test/validator_hash_test.rb +0 -93
  167. data/test/validator_integer_test.rb +0 -46
  168. data/test/validator_nil_test.rb +0 -13
  169. data/test/validator_number_test.rb +0 -60
  170. data/test/validator_object_test.rb +0 -139
  171. data/test/validator_string_test.rb +0 -76
  172. data/test/validator_symbol_test.rb +0 -16
@@ -0,0 +1,805 @@
1
+ require 'test_helper'
2
+
3
+ module Schemacop
4
+ module V3
5
+ class ArrayNodeTest < V3Test
6
+ EXP_INVALID_TYPE = 'Invalid type, expected "array".'.freeze
7
+
8
+ def test_basic
9
+ schema :array
10
+ assert_json(type: :array)
11
+ assert_validation []
12
+ assert_validation [nil, nil]
13
+ assert_validation [2234, 'foo', :bar]
14
+ end
15
+
16
+ def test_in_object
17
+ schema { ary! :items }
18
+ assert_json(
19
+ type: :object,
20
+ properties: {
21
+ items: { type: :array }
22
+ },
23
+ required: %i[items],
24
+ additionalProperties: false
25
+ )
26
+
27
+ assert_validation items: []
28
+ assert_validation items: [nil]
29
+ assert_validation items: [2234, 'foo', :bar]
30
+ end
31
+
32
+ def test_object_contents
33
+ schema :array do
34
+ hsh do
35
+ str! :name
36
+ end
37
+ end
38
+
39
+ assert_json(
40
+ type: :array,
41
+ items: [
42
+ {
43
+ type: :object,
44
+ properties: { name: { type: :string } },
45
+ required: %i[name],
46
+ additionalProperties: false
47
+ }
48
+ ],
49
+ additionalItems: false
50
+ )
51
+
52
+ assert_validation [{ name: 'Foo' }]
53
+ assert_validation [{ name: 'Foo' }, { name: 'Bar' }] do
54
+ error '/', 'Array has 2 items but must have exactly 1.'
55
+ end
56
+ assert_validation [123] do
57
+ error '/[0]', 'Invalid type, expected "object".'
58
+ end
59
+ end
60
+
61
+ def test_type
62
+ schema :array
63
+
64
+ assert_json(type: :array)
65
+
66
+ assert_validation 42 do
67
+ error '/', EXP_INVALID_TYPE
68
+ end
69
+
70
+ schema { ary! :foo }
71
+
72
+ assert_json(
73
+ type: :object,
74
+ properties: {
75
+ foo: { type: :array }
76
+ },
77
+ required: %i[foo],
78
+ additionalProperties: false
79
+ )
80
+
81
+ assert_validation foo: 42 do
82
+ error '/foo', EXP_INVALID_TYPE
83
+ end
84
+
85
+ assert_validation foo: {} do
86
+ error '/foo', EXP_INVALID_TYPE
87
+ end
88
+ end
89
+
90
+ def test_min_items
91
+ schema :array, min_items: 0
92
+
93
+ assert_json(type: :array, minItems: 0)
94
+ assert_validation []
95
+ assert_validation [1]
96
+
97
+ schema :array, min_items: 1
98
+
99
+ assert_json(type: :array, minItems: 1)
100
+ assert_validation [1]
101
+ assert_validation [1, 2]
102
+ assert_validation [] do
103
+ error '/', 'Array has 0 items but needs at least 1.'
104
+ end
105
+
106
+ schema :array, min_items: 5
107
+ assert_json(type: :array, minItems: 5)
108
+
109
+ assert_validation [1, 2, 3, 4] do
110
+ error '/', 'Array has 4 items but needs at least 5.'
111
+ end
112
+ end
113
+
114
+ def test_max_items
115
+ schema :array, max_items: 0
116
+
117
+ assert_json(type: :array, maxItems: 0)
118
+ assert_validation []
119
+
120
+ schema :array, max_items: 1
121
+
122
+ assert_json(type: :array, maxItems: 1)
123
+ assert_validation [1]
124
+ assert_validation [1, 2] do
125
+ error '/', 'Array has 2 items but needs at most 1.'
126
+ end
127
+
128
+ schema :array, max_items: 5
129
+
130
+ assert_json(type: :array, maxItems: 5)
131
+ assert_validation [1, 2, 3, 4, 5, 6] do
132
+ error '/', 'Array has 6 items but needs at most 5.'
133
+ end
134
+ end
135
+
136
+ def test_min_max_items
137
+ schema :array, min_items: 2, max_items: 4
138
+
139
+ assert_json(type: :array, minItems: 2, maxItems: 4)
140
+ assert_validation [1, 2]
141
+ assert_validation [1, 2, 3]
142
+ assert_validation [1, 2, 3, 4]
143
+
144
+ assert_validation [1] do
145
+ error '/', 'Array has 1 items but needs at least 2.'
146
+ end
147
+
148
+ assert_validation [1, 2, 3, 4, 5] do
149
+ error '/', 'Array has 5 items but needs at most 4.'
150
+ end
151
+ end
152
+
153
+ def test_unique_items
154
+ schema :array, unique_items: true
155
+
156
+ assert_json(type: :array, uniqueItems: true)
157
+ assert_validation [1, 2]
158
+ assert_validation [1, 2, :foo, 'bar', 'foo']
159
+
160
+ assert_validation [1, 1] do
161
+ error '/', 'Array has duplicate items.'
162
+ end
163
+
164
+ assert_validation [:foo, :foo] do
165
+ error '/', 'Array has duplicate items.'
166
+ end
167
+
168
+ assert_validation [1, 2, :foo, 'bar', 'foo'].as_json do
169
+ error '/', 'Array has duplicate items.'
170
+ end
171
+ end
172
+
173
+ def test_single_item_tuple
174
+ schema :array do
175
+ str
176
+ end
177
+
178
+ assert_json(
179
+ type: :array,
180
+ items: [
181
+ { type: :string }
182
+ ],
183
+ additionalItems: false
184
+ )
185
+
186
+ assert_validation [] do
187
+ error '/', 'Array has 0 items but must have exactly 1.'
188
+ end
189
+ assert_validation %w[foo]
190
+ assert_validation %w[foo bar] do
191
+ error '/', 'Array has 2 items but must have exactly 1.'
192
+ end
193
+
194
+ assert_validation ['foo', :bar] do
195
+ error '/', 'Array has 2 items but must have exactly 1.'
196
+ end
197
+
198
+ assert_validation %i[foo] do
199
+ error '/[0]', 'Invalid type, expected "string".'
200
+ end
201
+ end
202
+
203
+ def test_multiple_item_tuple
204
+ schema :array do
205
+ str
206
+ int
207
+ hsh do
208
+ str! :name
209
+ end
210
+ end
211
+
212
+ assert_json(
213
+ type: :array,
214
+ items: [
215
+ { type: :string },
216
+ { type: :integer },
217
+ { type: :object, properties: { name: { type: :string } }, required: %i[name], additionalProperties: false }
218
+ ],
219
+ additionalItems: false
220
+ )
221
+
222
+ assert_validation(['foo', 42, { name: 'Hello' }])
223
+
224
+ assert_validation [] do
225
+ error '/', 'Array has 0 items but must have exactly 3.'
226
+ end
227
+
228
+ assert_validation ['foo'] do
229
+ error '/', 'Array has 1 items but must have exactly 3.'
230
+ end
231
+
232
+ assert_validation([42, 42, { name: 'Hello' }]) do
233
+ error '/[0]', 'Invalid type, expected "string".'
234
+ end
235
+
236
+ assert_validation(['foo', 42, { namex: 'Hello' }]) do
237
+ error '/[2]/name', 'Value must be given.'
238
+ error '/[2]', 'Obsolete property "namex".'
239
+ end
240
+ end
241
+
242
+ def test_additional_items_true
243
+ schema :array, additional_items: true do
244
+ str
245
+ int
246
+ end
247
+
248
+ assert_json(
249
+ type: :array,
250
+ items: [
251
+ { type: :string },
252
+ { type: :integer }
253
+ ],
254
+ additionalItems: true
255
+ )
256
+
257
+ assert_validation(['foo', 42])
258
+ assert_validation(['foo', 42, 'additional'])
259
+ assert_validation(['foo', 42, 42])
260
+
261
+ assert_cast(['Foo', 42], ['Foo', 42])
262
+ assert_cast(['Foo', 42, 42], ['Foo', 42, 42])
263
+ assert_cast(['Foo', 42, :bar], ['Foo', 42, :bar])
264
+ end
265
+
266
+ def test_additional_items_true_casting
267
+ schema :array, additional_items: true do
268
+ str format: :date
269
+ int
270
+ end
271
+
272
+ assert_json(
273
+ type: :array,
274
+ items: [
275
+ { type: :string, format: :date },
276
+ { type: :integer }
277
+ ],
278
+ additionalItems: true
279
+ )
280
+
281
+ assert_validation(['1990-01-01', 42])
282
+ assert_validation(['1990-01-01', 42, 'additional'])
283
+ assert_validation(['1990-01-01', 42, 42])
284
+
285
+ assert_cast(['1990-01-01', 42], [Date.new(1990, 1, 1), 42])
286
+ assert_cast(['1990-01-01', 42, '2010-01-01'], [Date.new(1990, 1, 1), 42, '2010-01-01'])
287
+ assert_cast(['1990-01-01', 42, :bar], [Date.new(1990, 1, 1), 42, :bar])
288
+ end
289
+
290
+ def test_additional_items_single
291
+ schema :array do
292
+ str
293
+ add :integer
294
+ end
295
+
296
+ assert_json(
297
+ type: :array,
298
+ items: [
299
+ { type: :string }
300
+ ],
301
+ additionalItems: { type: :integer }
302
+ )
303
+
304
+ assert_validation(['foo'])
305
+ assert_validation(['foo', 42])
306
+ assert_validation(['foo', 42, 42])
307
+ assert_validation(['foo', :foo]) do
308
+ error '/[1]', 'Invalid type, expected "integer".'
309
+ end
310
+ end
311
+
312
+ def test_additional_items_schema
313
+ schema :array, additional_items: true do
314
+ str
315
+ int
316
+ add :string
317
+ end
318
+
319
+ assert_json(
320
+ type: :array,
321
+ items: [
322
+ { type: :string },
323
+ { type: :integer }
324
+ ],
325
+ additionalItems: { type: :string }
326
+ )
327
+
328
+ assert_validation(['foo', 42])
329
+ assert_validation(['foo', 42, 'additional', 'another'])
330
+ assert_validation(['foo', 42, 'additional', 42, 'another']) do
331
+ error '/[3]', 'Invalid type, expected "string".'
332
+ end
333
+
334
+ assert_cast(['foo', 42], ['foo', 42])
335
+ assert_cast(['foo', 42, 'bar'], ['foo', 42, 'bar'])
336
+ end
337
+
338
+ def test_additional_items_schema_casting
339
+ schema :array, additional_items: true do
340
+ str
341
+ int
342
+ add :string, format: :date
343
+ end
344
+
345
+ assert_json(
346
+ type: :array,
347
+ items: [
348
+ { type: :string },
349
+ { type: :integer }
350
+ ],
351
+ additionalItems: { type: :string, format: :date }
352
+ )
353
+
354
+ assert_validation(['foo', 42])
355
+ assert_validation(['foo', 42, '1990-01-01'])
356
+ assert_validation(['foo', 42, '1990-01-01', 42]) do
357
+ error '/[3]', 'Invalid type, expected "string".'
358
+ end
359
+ assert_validation(['foo', 42, '1990-01-01', 'foo']) do
360
+ error '/[3]', 'String does not match format "date".'
361
+ end
362
+
363
+ assert_cast(['foo', 42], ['foo', 42])
364
+ assert_cast(['foo', 42, '1990-01-01'], ['foo', 42, Date.new(1990, 1, 1)])
365
+ end
366
+
367
+ def test_additional_items_schema_oneof_casting
368
+ schema :array, additional_items: true do
369
+ str
370
+ int
371
+ add :one_of do
372
+ str format: :date
373
+ str format: :integer
374
+ end
375
+ end
376
+
377
+ assert_json(
378
+ type: :array,
379
+ items: [
380
+ { type: :string },
381
+ { type: :integer }
382
+ ],
383
+ additionalItems: {
384
+ oneOf: [
385
+ { type: :string, format: :date },
386
+ { type: :string, format: :integer }
387
+ ]
388
+ }
389
+ )
390
+
391
+ assert_validation(['foo', 42])
392
+ assert_validation(['foo', 42, '1990-01-01'])
393
+ assert_validation(['foo', 42, '1990-01-01', 42]) do
394
+ error '/[3]', 'Matches 0 definitions but should match exactly 1.'
395
+ end
396
+ assert_validation(['foo', 42, '1990-01-01', 'foo']) do
397
+ error '/[3]', 'Matches 0 definitions but should match exactly 1.'
398
+ end
399
+
400
+ assert_cast(['foo', 42], ['foo', 42])
401
+ assert_cast(['foo', 42, '1990-01-01'], ['foo', 42, Date.new(1990, 1, 1)])
402
+ assert_cast(['foo', 42, '1337'], ['foo', 42, 1337])
403
+ end
404
+
405
+ def test_additional_items_schema_hash_casting
406
+ schema :array, additional_items: true do
407
+ str
408
+ int
409
+ add :hash do
410
+ str! :foo, format: :date
411
+ sym? :bar
412
+ end
413
+ end
414
+
415
+ assert_json(
416
+ type: :array,
417
+ items: [
418
+ { type: :string },
419
+ { type: :integer }
420
+ ],
421
+ additionalItems: {
422
+ properties: {
423
+ foo: {
424
+ type: :string,
425
+ format: :date
426
+ },
427
+ bar: {}
428
+ },
429
+ additionalProperties: false,
430
+ type: :object,
431
+ required: [
432
+ :foo
433
+ ]
434
+ }
435
+ )
436
+
437
+ assert_validation(['foo', 42])
438
+ assert_validation(['foo', 42, { foo: '1990-01-01' }])
439
+ assert_validation(['foo', 42, { foo: '1990-01-01', bar: :baz }])
440
+
441
+ assert_validation(['foo', 42, { foo: 1234 }]) do
442
+ error '/[2]/foo', 'Invalid type, expected "string".'
443
+ end
444
+ assert_validation(['foo', 42, { foo: 'String' }]) do
445
+ error '/[2]/foo', 'String does not match format "date".'
446
+ end
447
+
448
+ assert_cast(['foo', 42], ['foo', 42])
449
+ assert_cast(['foo', 42, { foo: '1990-01-01' }], ['foo', 42, { foo: Date.new(1990, 1, 1) }])
450
+ assert_cast(['foo', 42, { foo: '1990-01-01', bar: :baz }], ['foo', 42, { foo: Date.new(1990, 1, 1), bar: :baz }])
451
+ end
452
+
453
+ def test_multiple_add_in_schema
454
+ assert_raises_with_message Exceptions::InvalidSchemaError,
455
+ 'You can only use "add" once to specify additional items.' do
456
+ schema :array do
457
+ add :integer
458
+ add :string
459
+ end
460
+ end
461
+ end
462
+
463
+ def test_contains
464
+ schema :array do
465
+ cont :string
466
+ end
467
+
468
+ assert_json(
469
+ type: :array,
470
+ contains: {
471
+ type: :string
472
+ }
473
+ )
474
+
475
+ assert_validation(%w[foo bar])
476
+ assert_validation(['foo', 42])
477
+ assert_validation(['foo'])
478
+
479
+ assert_validation([]) do
480
+ error '/', 'At least one entry must match schema {"type"=>"string"}.'
481
+ end
482
+
483
+ assert_validation([234, :foo]) do
484
+ error '/', 'At least one entry must match schema {"type"=>"string"}.'
485
+ end
486
+ end
487
+
488
+ def test_contains_int
489
+ schema :array do
490
+ cont :integer
491
+ end
492
+
493
+ assert_validation(['foo', 1, :bar])
494
+ assert_cast(['foo', 1, :bar], ['foo', 1, :bar])
495
+ end
496
+
497
+ def test_contains_with_casting
498
+ schema :array do
499
+ cont :string, format: :date
500
+ end
501
+
502
+ assert_validation(nil)
503
+ assert_validation(['1990-01-01'])
504
+
505
+ assert_cast(['1990-01-01'], [Date.new(1990, 1, 1)])
506
+ assert_cast(%w[1990-01-01 123], [Date.new(1990, 1, 1), '123'])
507
+ assert_cast(%w[1990-01-01 123 2010-01-01], [Date.new(1990, 1, 1), '123', Date.new(2010, 1, 1)])
508
+ end
509
+
510
+ def test_defaults
511
+ schema :array, default: [1, 2, 3]
512
+
513
+ assert_cast nil, [1, 2, 3]
514
+
515
+ assert_json(
516
+ type: :array,
517
+ default: [1, 2, 3]
518
+ )
519
+
520
+ schema :array do
521
+ hsh do
522
+ str? :name, default: 'John'
523
+ end
524
+ end
525
+
526
+ assert_json(
527
+ type: :array,
528
+ items: [
529
+ {
530
+ type: :object,
531
+ properties: {
532
+ name: { type: :string, default: 'John' }
533
+ },
534
+ additionalProperties: false
535
+ }
536
+ ],
537
+ additionalItems: false
538
+ )
539
+
540
+ assert_cast [{}], [{ name: 'John' }]
541
+ end
542
+
543
+ def test_enum_schema
544
+ schema :array, enum: [1, 2, 'foo', :bar, { qux: 42 }, [1, 2], %w[a b]]
545
+
546
+ assert_json({
547
+ type: :array,
548
+ enum: [1, 2, 'foo', :bar, { qux: 42 }, [1, 2], %w[a b]]
549
+ })
550
+
551
+ assert_validation(nil)
552
+ assert_validation([1, 2])
553
+ assert_validation(%w[a b])
554
+
555
+ # Even we put those types in the enum, they need to fail the validations,
556
+ # as they are not arrays
557
+ assert_validation('foo') do
558
+ error '/', 'Invalid type, expected "array".'
559
+ end
560
+ assert_validation(1) do
561
+ error '/', 'Invalid type, expected "array".'
562
+ end
563
+ assert_validation(:bar) do
564
+ error '/', 'Invalid type, expected "array".'
565
+ end
566
+ assert_validation({ qux: 42 }) do
567
+ error '/', 'Invalid type, expected "array".'
568
+ end
569
+
570
+ # These need to fail validation, as they are not in the enum list
571
+ assert_validation([1, 2, 3]) do
572
+ error '/', 'Value not included in enum [1, 2, "foo", :bar, {:qux=>42}, [1, 2], ["a", "b"]].'
573
+ end
574
+ assert_validation([]) do
575
+ error '/', 'Value not included in enum [1, 2, "foo", :bar, {:qux=>42}, [1, 2], ["a", "b"]].'
576
+ end
577
+ end
578
+
579
+ def test_with_generic_keywords
580
+ schema :array, enum: [1, 'foo', [1, 2, 3]],
581
+ title: 'Array schema',
582
+ description: 'Array schema holding generic keywords',
583
+ examples: [
584
+ [1, 2, 3]
585
+ ]
586
+
587
+ assert_json({
588
+ type: :array,
589
+ enum: [1, 'foo', [1, 2, 3]],
590
+ title: 'Array schema',
591
+ description: 'Array schema holding generic keywords',
592
+ examples: [
593
+ [1, 2, 3]
594
+ ]
595
+ })
596
+ end
597
+
598
+ # Helper function that checks for the min_items and max_items options if the option is
599
+ # an integer or something else, in which case it needs to raise
600
+ def validate_self_should_error(value_to_check)
601
+ assert_raises_with_message Exceptions::InvalidSchemaError,
602
+ 'Option "min_items" must be an "integer"' do
603
+ schema :array, min_items: value_to_check
604
+ end
605
+
606
+ assert_raises_with_message Exceptions::InvalidSchemaError,
607
+ 'Option "max_items" must be an "integer"' do
608
+ schema :array, max_items: value_to_check
609
+ end
610
+ end
611
+
612
+ def test_validate_self
613
+ assert_raises_with_message Exceptions::InvalidSchemaError,
614
+ 'Option "min_items" can\'t be greater than "max_items".' do
615
+ schema :array, min_items: 5, max_items: 4
616
+ end
617
+
618
+ assert_raises_with_message Exceptions::InvalidSchemaError,
619
+ 'Option "unique_items" must be a "boolean".' do
620
+ schema :array, unique_items: 4
621
+ end
622
+
623
+ assert_raises_with_message Exceptions::InvalidSchemaError,
624
+ 'Option "unique_items" must be a "boolean".' do
625
+ schema :array, unique_items: 'false'
626
+ end
627
+
628
+ validate_self_should_error(1.0)
629
+ validate_self_should_error(4r)
630
+ validate_self_should_error(true)
631
+ validate_self_should_error(false)
632
+ validate_self_should_error(Object.new)
633
+ validate_self_should_error((4 + 6i))
634
+ validate_self_should_error('13')
635
+ validate_self_should_error('Lorem ipsum')
636
+ end
637
+
638
+ def test_list
639
+ assert_raises_with_message Exceptions::InvalidSchemaError,
640
+ 'You can only use "list" once.' do
641
+ schema :array do
642
+ list :integer
643
+ list :symbol
644
+ end
645
+ end
646
+
647
+ assert_raises_with_message Exceptions::InvalidSchemaError,
648
+ 'Can\'t use "list" and normal items.' do
649
+ schema :array do
650
+ list :integer
651
+ int
652
+ end
653
+ end
654
+
655
+ assert_raises_with_message Exceptions::InvalidSchemaError,
656
+ 'Can\'t use "list" and additional items.' do
657
+ schema :array do
658
+ list :integer
659
+ add :symbol
660
+ end
661
+ end
662
+
663
+ schema :array do
664
+ list :integer
665
+ end
666
+
667
+ assert_validation([])
668
+ assert_validation([1])
669
+ assert_validation([1, 2, 3, 4, 5, 6])
670
+
671
+ assert_validation([1, :foo, 'bar']) do
672
+ error '/[1]', 'Invalid type, expected "integer".'
673
+ error '/[2]', 'Invalid type, expected "integer".'
674
+ end
675
+ end
676
+
677
+ def test_list_casting
678
+ schema :array do
679
+ list :string, format: :date
680
+ end
681
+
682
+ assert_json(
683
+ type: :array,
684
+ items: {
685
+ type: :string,
686
+ format: :date
687
+ }
688
+ )
689
+
690
+ assert_validation(nil)
691
+ assert_validation(['1990-01-01'])
692
+ assert_validation(%w[1990-01-01 2020-01-01])
693
+ assert_validation(['foo']) do
694
+ error '/[0]', 'String does not match format "date".'
695
+ end
696
+
697
+ assert_cast(['1990-01-01'], [Date.new(1990, 1, 1)])
698
+ end
699
+
700
+ def test_simple_contains
701
+ schema :array do
702
+ cont :integer, minimum: 3
703
+ end
704
+
705
+ assert_json(
706
+ type: :array,
707
+ contains: {
708
+ type: :integer,
709
+ minimum: 3
710
+ }
711
+ )
712
+
713
+ assert_validation(nil)
714
+ assert_validation([]) do
715
+ error '/', 'At least one entry must match schema {"type"=>"integer", "minimum"=>3}.'
716
+ end
717
+ assert_validation([1, 2]) do
718
+ error '/', 'At least one entry must match schema {"type"=>"integer", "minimum"=>3}.'
719
+ end
720
+ assert_validation([1, 2, 3])
721
+ end
722
+
723
+ def test_contains_with_list
724
+ schema :array do
725
+ list :integer, minimum: 2
726
+ cont :integer, minimum: 5
727
+ end
728
+
729
+ assert_json(
730
+ type: :array,
731
+ contains: {
732
+ type: :integer,
733
+ minimum: 5
734
+ },
735
+ items: {
736
+ type: :integer,
737
+ minimum: 2
738
+ }
739
+ )
740
+
741
+ assert_validation(nil)
742
+ assert_validation([]) do
743
+ error '/', 'At least one entry must match schema {"type"=>"integer", "minimum"=>5}.'
744
+ end
745
+ assert_validation([1]) do
746
+ error '/', 'At least one entry must match schema {"type"=>"integer", "minimum"=>5}.'
747
+ error '/[0]', 'Value must have a minimum of 2.'
748
+ end
749
+ assert_validation([2]) do
750
+ error '/', 'At least one entry must match schema {"type"=>"integer", "minimum"=>5}.'
751
+ end
752
+
753
+ assert_validation([2, 3, 5])
754
+ end
755
+
756
+ def test_contains_need_casting
757
+ schema :array do
758
+ cont :string, format: :date
759
+ end
760
+
761
+ assert_json(
762
+ type: :array,
763
+ contains: {
764
+ type: :string,
765
+ format: :date
766
+ }
767
+ )
768
+
769
+ assert_validation(nil)
770
+ assert_validation(['1990-01-01'])
771
+ assert_validation(['1990-01-01', 1234])
772
+
773
+ assert_cast(['1990-01-01'], [Date.new(1990, 1, 1)])
774
+ assert_cast(%w[1990-01-01 123], [Date.new(1990, 1, 1), '123'])
775
+ assert_cast(%w[1990-01-01 123 2010-01-01], [Date.new(1990, 1, 1), '123', Date.new(2010, 1, 1)])
776
+ end
777
+
778
+ def test_contains_with_list_casting
779
+ schema :array do
780
+ list :string
781
+ cont :string, format: :date
782
+ end
783
+
784
+ assert_json(
785
+ type: :array,
786
+ items: {
787
+ type: :string
788
+ },
789
+ contains: {
790
+ type: :string,
791
+ format: :date
792
+ }
793
+ )
794
+
795
+ assert_validation(nil)
796
+ assert_validation(['foo']) do
797
+ error '/', 'At least one entry must match schema {"type"=>"string", "format"=>"date"}.'
798
+ end
799
+ assert_validation(%w[foo 1990-01-01])
800
+
801
+ assert_cast(%w[foo 1990-01-01], ['foo', Date.new(1990, 1, 1)])
802
+ end
803
+ end
804
+ end
805
+ end