schemacop 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +59 -1
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +389 -199
  6. data/Rakefile +2 -0
  7. data/VERSION +1 -1
  8. data/doc/Schemacop.html +41 -130
  9. data/doc/Schemacop/ArrayValidator.html +329 -0
  10. data/doc/Schemacop/BooleanValidator.html +145 -0
  11. data/doc/Schemacop/Collector.html +535 -0
  12. data/doc/Schemacop/Exceptions.html +39 -39
  13. data/doc/Schemacop/Exceptions/InvalidSchemaError.html +124 -0
  14. data/doc/Schemacop/Exceptions/ValidationError.html +124 -0
  15. data/doc/Schemacop/FieldNode.html +409 -0
  16. data/doc/Schemacop/FloatValidator.html +158 -0
  17. data/doc/Schemacop/HashValidator.html +263 -0
  18. data/doc/Schemacop/IntegerValidator.html +158 -0
  19. data/doc/Schemacop/NilValidator.html +145 -0
  20. data/doc/Schemacop/Node.html +1426 -0
  21. data/doc/Schemacop/NodeResolver.html +242 -0
  22. data/doc/Schemacop/NodeSupportingField.html +590 -0
  23. data/doc/Schemacop/NodeSupportingType.html +614 -0
  24. data/doc/Schemacop/NodeWithBlock.html +289 -0
  25. data/doc/Schemacop/NumberValidator.html +232 -0
  26. data/doc/Schemacop/ObjectValidator.html +288 -0
  27. data/doc/Schemacop/RootNode.html +171 -0
  28. data/doc/Schemacop/Schema.html +697 -0
  29. data/doc/Schemacop/StringValidator.html +295 -0
  30. data/doc/ScopedEnv.html +351 -0
  31. data/doc/_index.html +190 -47
  32. data/doc/class_list.html +24 -31
  33. data/doc/css/full_list.css +32 -31
  34. data/doc/css/style.css +244 -91
  35. data/doc/file.README.html +428 -232
  36. data/doc/file_list.html +26 -30
  37. data/doc/frames.html +7 -16
  38. data/doc/index.html +428 -232
  39. data/doc/inheritance.graphml +524 -0
  40. data/doc/inheritance.pdf +825 -0
  41. data/doc/js/app.js +106 -77
  42. data/doc/js/full_list.js +170 -135
  43. data/doc/method_list.html +494 -38
  44. data/doc/top-level-namespace.html +36 -36
  45. data/lib/schemacop.rb +22 -7
  46. data/lib/schemacop/collector.rb +34 -0
  47. data/lib/schemacop/exceptions.rb +2 -8
  48. data/lib/schemacop/field_node.rb +26 -0
  49. data/lib/schemacop/node.rb +127 -0
  50. data/lib/schemacop/node_resolver.rb +14 -0
  51. data/lib/schemacop/node_supporting_field.rb +62 -0
  52. data/lib/schemacop/node_supporting_type.rb +112 -0
  53. data/lib/schemacop/node_with_block.rb +16 -0
  54. data/lib/schemacop/root_node.rb +4 -0
  55. data/lib/schemacop/schema.rb +61 -0
  56. data/lib/schemacop/scoped_env.rb +18 -0
  57. data/lib/schemacop/validator/array_validator.rb +30 -0
  58. data/lib/schemacop/validator/boolean_validator.rb +5 -0
  59. data/lib/schemacop/validator/float_validator.rb +5 -0
  60. data/lib/schemacop/validator/hash_validator.rb +18 -0
  61. data/lib/schemacop/validator/integer_validator.rb +5 -0
  62. data/lib/schemacop/validator/nil_validator.rb +5 -0
  63. data/lib/schemacop/validator/number_validator.rb +19 -0
  64. data/lib/schemacop/validator/object_validator.rb +21 -0
  65. data/lib/schemacop/validator/string_validator.rb +37 -0
  66. data/schemacop.gemspec +7 -5
  67. data/test/custom_check_test.rb +86 -0
  68. data/test/custom_if_test.rb +95 -0
  69. data/test/nil_dis_allow_test.rb +41 -0
  70. data/test/short_forms_test.rb +316 -0
  71. data/test/test_helper.rb +6 -0
  72. data/test/types_test.rb +83 -0
  73. data/test/validator_array_test.rb +97 -0
  74. data/test/validator_boolean_test.rb +15 -0
  75. data/test/validator_float_test.rb +57 -0
  76. data/test/validator_hash_test.rb +71 -0
  77. data/test/validator_integer_test.rb +46 -0
  78. data/test/validator_nil_test.rb +13 -0
  79. data/test/validator_number_test.rb +60 -0
  80. data/test/validator_object_test.rb +87 -0
  81. data/test/validator_string_test.rb +76 -0
  82. metadata +78 -14
  83. data/doc/Schemacop/Exceptions/Base.html +0 -127
  84. data/doc/Schemacop/Exceptions/InvalidSchema.html +0 -141
  85. data/doc/Schemacop/Exceptions/Validation.html +0 -142
  86. data/doc/Schemacop/MethodValidation.html +0 -120
  87. data/doc/Schemacop/MethodValidation/ClassMethods.html +0 -196
  88. data/doc/Schemacop/Validator.html +0 -254
  89. data/lib/schemacop/validator.rb +0 -145
  90. data/test/schemacop_validator_test.rb +0 -257
@@ -0,0 +1,95 @@
1
+ require 'test_helper'
2
+
3
+ module Schemacop
4
+ class CustomIfTest < Minitest::Test
5
+ def test_allowed_subset_only
6
+ s = Schema.new do
7
+ type :integer, if: proc { |data| data.odd? }
8
+ end
9
+
10
+ assert_nil s.validate! 5
11
+ assert_verr { s.validate! nil }
12
+ assert_verr { s.validate! 4 }
13
+ end
14
+
15
+ def test_if_with_multiple_types
16
+ s = Schema.new do
17
+ type :integer, if: proc { |data| data.odd? }
18
+ type :string
19
+ end
20
+
21
+ assert_nil s.validate!(5)
22
+ assert_nil s.validate!('abc')
23
+ assert_verr { s.validate!(4) }
24
+ end
25
+
26
+ def test_if_with_string
27
+ s = Schema.new do
28
+ req :foo, :string, if: proc { |data| data.start_with?('a') }, min: 3
29
+ req :foo, :string, min: 5
30
+ end
31
+
32
+ assert_nil s.validate!(foo: 'abc')
33
+ assert_nil s.validate!(foo: 'bcdef')
34
+ assert_verr { s.validate!(foo: 'a') }
35
+ assert_verr { s.validate!(foo: 'bcde') }
36
+ end
37
+
38
+ def test_if_with_multiple_types_in_field
39
+ s = Schema.new do
40
+ req :foo, :string, if: proc { |data| data.start_with?('a') }
41
+ req :foo, :integer
42
+ end
43
+
44
+ assert_nil s.validate!(foo: 3)
45
+ assert_nil s.validate!(foo: 'abc')
46
+ assert_verr { s.validate!(foo: 'bcd') }
47
+ assert_verr { s.validate!(foo: true) }
48
+ end
49
+
50
+ def test_if_with_hash_in_array
51
+ s = Schema.new do
52
+ req :user, :array do
53
+ type :hash, if: proc { |data| data[:admin] } do
54
+ req :admin, :boolean
55
+ req :admin_only, :string
56
+ end
57
+ type :hash do
58
+ opt :admin
59
+ req :non_admin_only, :string
60
+ end
61
+ end
62
+ end
63
+
64
+ assert_nil s.validate!(user: [{ admin: true, admin_only: 'foo' }, { admin: false, non_admin_only: 'foo' }])
65
+ assert_nil s.validate!(user: [{ admin: true, admin_only: 'foo' }, { non_admin_only: 'foo' }])
66
+ assert_verr { s.validate!(user: [{ admin: false, admin_only: 'foo' }]) }
67
+ assert_verr { s.validate!(user: [{ admin: true, non_admin_only: 'foo' }]) }
68
+ end
69
+
70
+ def test_if_true_or_false
71
+ s = Schema.new do
72
+ req :foo, :integer, if: proc { true }, min: 5
73
+ req :bar, :integer, if: proc { false }, min: 5
74
+ # TODO: It should work without the following line
75
+ req :bar, :integer
76
+ end
77
+
78
+ assert_nil s.validate!(foo: 5, bar: 5)
79
+ assert_nil s.validate!(foo: 5, bar: 4)
80
+ assert_verr { s.validate!(foo: 4, bar: 5) }
81
+ assert_verr { s.validate!(foo: 4, bar: 4) }
82
+ end
83
+
84
+ def test_mixed_req_opt
85
+ s = Schema.new do
86
+ req :foo, :integer, if: proc { |data| !data.nil? }
87
+ opt :foo, :integer
88
+ end
89
+
90
+ assert_nil s.validate!(foo: 4)
91
+ assert_verr { s.validate!({}) }
92
+ assert_verr { s.validate!('something') }
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ # Note: A test for req and opt is part of validator_hash_test.rb
4
+
5
+ module Schemacop
6
+ class NilDisAllowTest < Minitest::Test
7
+ def test_req
8
+ s = Schema.new do
9
+ req? :o do
10
+ type :boolean
11
+ end
12
+
13
+ req :r do
14
+ type :boolean
15
+ end
16
+ end
17
+ assert_nil s.validate!(o: nil, r: false)
18
+ assert_nil s.validate!(o: false, r: false)
19
+ assert_verr { s.validate!(o: true, r: nil) }
20
+ assert_verr { s.validate!(o: nil, r: nil) }
21
+ assert_verr { s.validate!(r: true) }
22
+ end
23
+
24
+ def test_opt
25
+ s = Schema.new do
26
+ opt :o do
27
+ type :boolean
28
+ end
29
+ opt! :r do
30
+ type :boolean
31
+ end
32
+ end
33
+ assert_nil s.validate!(o: nil, r: false)
34
+ assert_nil s.validate!(o: false, r: false)
35
+ assert_nil s.validate!(r: true)
36
+ assert_nil s.validate!({})
37
+ assert_verr { s.validate!(o: true, r: nil) }
38
+ assert_verr { s.validate!(o: nil, r: nil) }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,316 @@
1
+ require 'test_helper'
2
+
3
+ module Schemacop
4
+ class ShortFormsTest < Minitest::Test
5
+ def test_constructor_defaults_to_hash
6
+ s = Schema.new do
7
+ req! :r do
8
+ type :integer
9
+ end
10
+ opt? :o do
11
+ type :integer
12
+ end
13
+ end
14
+
15
+ assert_nil s.validate!(r: 3)
16
+ assert_nil s.validate!(r: 3, o: 1)
17
+ assert_verr { s.validate!(o: 1) }
18
+ assert_verr { s.validate!(1) }
19
+ assert_verr { s.validate!(r: 3, n: 5) }
20
+ end
21
+
22
+ def test_field_defaults_to_any
23
+ s = Schema.new do
24
+ type :hash do
25
+ req :r
26
+ opt :o
27
+ end
28
+ end
29
+
30
+ assert_nil s.validate!(r: 3)
31
+ assert_nil s.validate!(r: 'asd', o: self)
32
+ assert_verr { s.validate!(o: -5.3) }
33
+ assert_verr { s.validate!(Class) }
34
+ assert_verr { s.validate!(r: s, n: true) }
35
+ end
36
+
37
+ def test_inline_type_with_attrs_in_hash
38
+ s = Schema.new do
39
+ type :hash do
40
+ req :i, :integer, min: 5
41
+ opt :f, :float, min: 2.3, max: 3
42
+ end
43
+ end
44
+
45
+ assert_nil s.validate!(i: 5)
46
+ assert_nil s.validate!(i: 5, f: 2.3)
47
+ assert_verr { s.validate!(i: 4, f: 2.3) }
48
+ assert_verr { s.validate!(i: 5, f: 2.2) }
49
+ assert_verr { s.validate!(i: 5, f: 3.4) }
50
+ assert_verr { s.validate!(i: 5.3) }
51
+ assert_verr { s.validate!(j: 2.3) }
52
+ assert_verr { s.validate!({}) }
53
+ end
54
+
55
+ def test_inline_type_in_constructor
56
+ s = Schema.new :integer, min: 2, max: 4
57
+ assert_nil s.validate!(3)
58
+ assert_verr { s.validate!(5) }
59
+ assert_verr { s.validate!(1) }
60
+ end
61
+
62
+ def test_mixed_field_and_type_attrs
63
+ s = Schema.new do
64
+ req? :nilbool, :boolean
65
+ req? :nilint, :integer, min: 2, max: 3
66
+ opt! :optint, :integer, min: 2, max: 3
67
+ end
68
+
69
+ assert_nil s.validate!(nilbool: nil, nilint: nil)
70
+ assert_nil s.validate!(nilbool: false, nilint: 2)
71
+ assert_nil s.validate!(nilbool: false, nilint: 3, optint: 2)
72
+ assert_verr { s.validate!(nilbool: false, nilint: 2, optint: nil) }
73
+ assert_verr { s.validate!(nilbool: false, nilint: 2, optint: 4) }
74
+ assert_verr { s.validate!(nilbool: false, nilint: -5, optint: 2) }
75
+ end
76
+
77
+ def test_array_shortform_simple
78
+ s = Schema.new do
79
+ type(:array, :string)
80
+ end
81
+ assert_nil s.validate!(%w(a b))
82
+ end
83
+
84
+ # TODO: Get the exception message into the assertion
85
+ def test_array_shortform_invalid
86
+ assert_raises Exceptions::InvalidSchemaError do
87
+ Schema.new do
88
+ type(:array, [:array, :integer], min: 2)
89
+ end
90
+ end
91
+ end
92
+
93
+ def test_array_shortform_advanced1
94
+ s = Schema.new do
95
+ type(:array, [:array, :integer])
96
+ end
97
+ assert_nil s.validate! [[], 3]
98
+ assert_nil s.validate! [[:a, 9], 3]
99
+ assert_nil s.validate! [[]]
100
+ assert_nil s.validate! [3]
101
+ assert_verr { s.validate! [[], 'string'] }
102
+ assert_verr { s.validate! [3, 'string'] }
103
+ assert_verr { s.validate! ['string'] }
104
+ end
105
+
106
+ def test_array_shortform_advanced2
107
+ assert_raises Exceptions::InvalidSchemaError, 'No validation class found for type [:array, :integer].' do
108
+ Schema.new do
109
+ type([:array, [:array, :integer], :boolean])
110
+ end
111
+ end
112
+ end
113
+
114
+ # For explicit form test see types_test.rb
115
+ def test_array_subtype_shortform
116
+ s = Schema.new do
117
+ type :array, :integer
118
+ end
119
+ assert_nil s.validate! [5]
120
+ assert_verr { s.validate! [nil] }
121
+ assert_verr { s.validate! ['a'] }
122
+ assert_verr { s.validate! [5, 'a'] }
123
+ assert_verr { s.validate! [5, nil] }
124
+ end
125
+
126
+ def test_array_subsubtype_shortform
127
+ s = Schema.new do
128
+ type :array, :array, :integer
129
+ end
130
+ assert_nil s.validate! [[5]]
131
+ assert_verr { s.validate! [5] }
132
+ assert_verr { s.validate! [[nil]] }
133
+ assert_verr { s.validate! [['a']] }
134
+ assert_verr { s.validate! [[5, 'a']] }
135
+ assert_verr { s.validate! [[5, nil]] }
136
+ end
137
+
138
+ def test_wild_mix_should_pass
139
+ s = Schema.new do
140
+ req :foo do
141
+ req? :bar, :object, classes: NilClass
142
+ end
143
+ req :name, :integer, min: 5, max: 7
144
+ req :id, [:integer, :string]
145
+ req :attrs do
146
+ req :color do
147
+ type :integer
148
+ end
149
+ end
150
+ req :colors, :array, [:string, :integer]
151
+ req :cars, :array, :hash do
152
+ req? :years, :array, :integer
153
+ req! :make, :string
154
+ req! :ps, :integer
155
+ req? :electric, :boolean
156
+ end
157
+ end
158
+
159
+ assert_nil s.validate!(
160
+ name: 6,
161
+ foo: { bar: nil },
162
+ attrs: { color: 5 },
163
+ id: 'hallo',
164
+ colors: [5, 'sdf'],
165
+ cars: [
166
+ {
167
+ make: 'Tesla',
168
+ ps: 5,
169
+ electric: nil,
170
+ years: [1993, 1990]
171
+ }
172
+ ]
173
+ )
174
+ end
175
+
176
+ def test_super_deep_wild_should_pass
177
+ s = Schema.new do
178
+ type :hash do
179
+ opt? :bla do
180
+ type :string
181
+ end
182
+ req :id do
183
+ type :string
184
+ end
185
+ req? :friends do
186
+ type :array do
187
+ type :string, min: 3, max: 6
188
+ type :boolean
189
+ type :hash do
190
+ req :rod do
191
+ type :hash do
192
+ req :fritz do
193
+ type :array, min: 2 do
194
+ type :array do
195
+ type :integer, min: 1
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ type :integer, min: 3
206
+ end
207
+
208
+ assert_nil s.validate!(
209
+ id: 'meine ID',
210
+ friends: [
211
+ 'Rodney',
212
+ true,
213
+ false,
214
+ {
215
+ rod: {
216
+ fritz:
217
+ [
218
+ [1],
219
+ [3]
220
+ ]
221
+ }
222
+ }
223
+ ]
224
+ )
225
+ assert_nil s.validate!(id: 'my ID', friends: nil)
226
+ assert_nil s.validate!(3)
227
+ end
228
+
229
+ def test_example_from_readme
230
+ schema = Schema.new do
231
+ req :naming, :hash do
232
+ opt :first_name, :string
233
+ req :last_name, :string
234
+ end
235
+ opt! :age, :integer, min: 18
236
+ req? :password do
237
+ type :string, check: proc { |pw| pw.include?('*') }
238
+ type :integer
239
+ end
240
+ end
241
+
242
+ assert_nil schema.validate!(
243
+ naming: { first_name: 'John',
244
+ last_name: 'Doe' },
245
+ age: 34,
246
+ password: 'my*pass'
247
+ )
248
+
249
+ assert_verr do
250
+ schema.validate!(
251
+ naming: { first_name: 'John',
252
+ last_name: 'Doe' },
253
+ age: 12,
254
+ password: 'my*pass'
255
+ )
256
+ end
257
+ assert_verr do
258
+ schema.validate!(
259
+ naming: { first_name: 'John',
260
+ last_name: 'Doe' },
261
+ age: 12,
262
+ password: 'mypass'
263
+ )
264
+ end
265
+
266
+ schema2 = Schema.new do
267
+ req :description,
268
+ :string,
269
+ if: proc { |str| str.start_with?('Abstract: ') },
270
+ max: 35,
271
+ check: proc { |str| !str.end_with?('.') }
272
+ req :description, :string, min: 35
273
+ end
274
+
275
+ assert_nil schema2.validate!(description: 'Abstract: a short description')
276
+ assert_nil schema2.validate!(description: 'Since this is no abstract, we expect it to be longer.')
277
+ assert_verr { schema2.validate!(description: 'Abstract: A short description.') }
278
+ assert_verr { schema2.validate!(description: 'Abstract: This is gonna be way way too long for an abstract.') }
279
+ assert_verr { schema2.validate!(description: 'This is too short.') }
280
+ end
281
+
282
+ def test_one_line_subtype_with_options
283
+ s = Schema.new do
284
+ type :array, :integer, min: 3
285
+ end
286
+ assert_nil s.validate!([3])
287
+ assert_nil s.validate!([3, 4, 5])
288
+ assert_verr { s.validate!([3, 2]) }
289
+ assert_verr { s.validate!([5, 'string']) }
290
+ end
291
+
292
+ def test_one_line_array_schema
293
+ s = Schema.new :array, :integer, min: 3
294
+ assert_nil s.validate!([3])
295
+ assert_nil s.validate!([3, 4, 5])
296
+ assert_verr { s.validate!([3, 2]) }
297
+ assert_verr { s.validate!([5, 'string']) }
298
+ end
299
+
300
+ def test_implicit_hash
301
+ s = Schema.new do
302
+ req :bar
303
+ end
304
+ assert_nil s.validate!(bar: 2)
305
+ assert_verr { s.validate!(foo: 2) }
306
+ assert_verr { s.validate!([2]) }
307
+ end
308
+
309
+ def test_one_line_string_schema
310
+ s = Schema.new :string, min: 4
311
+ assert_nil s.validate!('1234')
312
+ assert_verr { s.validate!('123') }
313
+ assert_verr { s.validate!(string: '1234') }
314
+ end
315
+ end
316
+ end