schemacop 1.0.2 → 2.0.0

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