schemacop 2.4.5 → 3.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +25 -1
  4. data/.travis.yml +3 -1
  5. data/CHANGELOG.md +32 -1
  6. data/README.md +53 -710
  7. data/README_V2.md +775 -0
  8. data/README_V3.md +1195 -0
  9. data/Rakefile +8 -12
  10. data/VERSION +1 -1
  11. data/lib/schemacop.rb +35 -36
  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/v2/node_supporting_field.rb +70 -0
  26. data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +14 -11
  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 +218 -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 +256 -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 +215 -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 +198 -0
  86. data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
  87. data/test/unit/schemacop/v3/array_node_test.rb +815 -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 +884 -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/node_supporting_field.rb +0 -58
  145. data/lib/schemacop/root_node.rb +0 -4
  146. data/lib/schemacop/validator/array_validator.rb +0 -30
  147. data/lib/schemacop/validator/float_validator.rb +0 -5
  148. data/lib/schemacop/validator/hash_validator.rb +0 -35
  149. data/lib/schemacop/validator/integer_validator.rb +0 -5
  150. data/lib/schemacop/validator/number_validator.rb +0 -19
  151. data/lib/schemacop/validator/object_validator.rb +0 -27
  152. data/lib/schemacop/validator/string_validator.rb +0 -37
  153. data/test/casting_test.rb +0 -90
  154. data/test/collector_test.rb +0 -45
  155. data/test/custom_check_test.rb +0 -93
  156. data/test/custom_if_test.rb +0 -95
  157. data/test/defaults_test.rb +0 -93
  158. data/test/empty_test.rb +0 -14
  159. data/test/nil_dis_allow_test.rb +0 -41
  160. data/test/node_resolver_test.rb +0 -26
  161. data/test/short_forms_test.rb +0 -349
  162. data/test/test_helper.rb +0 -13
  163. data/test/types_test.rb +0 -84
  164. data/test/validator_array_test.rb +0 -97
  165. data/test/validator_boolean_test.rb +0 -15
  166. data/test/validator_float_test.rb +0 -57
  167. data/test/validator_hash_test.rb +0 -93
  168. data/test/validator_integer_test.rb +0 -46
  169. data/test/validator_nil_test.rb +0 -13
  170. data/test/validator_number_test.rb +0 -60
  171. data/test/validator_object_test.rb +0 -139
  172. data/test/validator_string_test.rb +0 -76
  173. data/test/validator_symbol_test.rb +0 -16
@@ -0,0 +1,187 @@
1
+ require 'test_helper'
2
+
3
+ module Schemacop
4
+ module V3
5
+ class OneOfNodeTest < V3Test
6
+ def test_optional
7
+ schema :one_of do
8
+ num multiple_of: 2
9
+ num multiple_of: 3
10
+ str
11
+ end
12
+
13
+ assert_validation(nil)
14
+ assert_validation(4)
15
+ assert_validation(9)
16
+ assert_validation('foo')
17
+ assert_validation(12) do
18
+ error '/', 'Matches 2 definitions but should match exactly 1.'
19
+ end
20
+ assert_validation(1) do
21
+ error '/', 'Matches 0 definitions but should match exactly 1.'
22
+ end
23
+ assert_validation(:foo) do
24
+ error '/', 'Matches 0 definitions but should match exactly 1.'
25
+ end
26
+ end
27
+
28
+ def test_required
29
+ schema :one_of, required: true do
30
+ num multiple_of: 2
31
+ num multiple_of: 3
32
+ str
33
+ end
34
+
35
+ assert_validation(8)
36
+ assert_validation(9)
37
+
38
+ assert_validation(nil) do
39
+ error '/', 'Value must be given.'
40
+ end
41
+ end
42
+
43
+ def test_nested
44
+ schema :one_of do
45
+ hsh do
46
+ one_of! :foo do
47
+ num multiple_of: 2
48
+ num multiple_of: 3
49
+ end
50
+ end
51
+ hsh do
52
+ num? :foo, multiple_of: 7
53
+ end
54
+ end
55
+
56
+ assert_validation(foo: 2)
57
+ assert_validation(foo: 9)
58
+ assert_validation(foo: 7)
59
+ assert_validation(foo: 14) do
60
+ error '/', 'Matches 2 definitions but should match exactly 1.'
61
+ end
62
+ assert_validation(foo: 12) do
63
+ error '/', 'Matches 0 definitions but should match exactly 1.'
64
+ end
65
+
66
+ assert_json(
67
+ oneOf: [
68
+ {
69
+ type: :object,
70
+ properties: {
71
+ foo: {
72
+ oneOf: [
73
+ { type: :number, multipleOf: 2 },
74
+ { type: :number, multipleOf: 3 }
75
+ ]
76
+ }
77
+ },
78
+ required: %i[foo],
79
+ additionalProperties: false
80
+ },
81
+ {
82
+ type: :object,
83
+ properties: {
84
+ foo: { type: :number, multipleOf: 7 }
85
+ },
86
+ additionalProperties: false
87
+ }
88
+ ]
89
+ )
90
+ end
91
+
92
+ def test_casting
93
+ schema do
94
+ one_of! :created_at do
95
+ str format: :date
96
+ str format: :date_time
97
+ end
98
+ end
99
+
100
+ assert_validation(created_at: '2020-01-01')
101
+ assert_validation(created_at: '2020-01-01T17:38:20')
102
+
103
+ assert_cast(
104
+ { created_at: '2020-01-01' },
105
+ { created_at: Date.new(2020, 1, 1) }.with_indifferent_access
106
+ )
107
+ assert_cast(
108
+ { created_at: '2020-01-01T17:38:20' },
109
+ { created_at: DateTime.new(2020, 1, 1, 17, 38, 20) }.with_indifferent_access
110
+ )
111
+ end
112
+
113
+ def test_defaults
114
+ schema do
115
+ one_of! :foo do
116
+ hsh { str? :bar }
117
+ hsh { str? :baz, default: 'Baz' }
118
+ end
119
+ end
120
+
121
+ assert_validation(foo: { bar: 'Bar' })
122
+ assert_validation(foo: { baz: 'Baz' })
123
+
124
+ assert_validation(foo: { xyz: 'Baz' }) do
125
+ error '/foo', 'Matches 0 definitions but should match exactly 1.'
126
+ end
127
+
128
+ assert_cast(
129
+ { foo: { bar: nil } },
130
+ { foo: { bar: nil } }.with_indifferent_access
131
+ )
132
+
133
+ assert_cast(
134
+ { foo: { baz: nil } },
135
+ { foo: { baz: 'Baz' } }.with_indifferent_access
136
+ )
137
+
138
+ schema do
139
+ one_of! :foo do
140
+ hsh { str? :bar, format: :date }
141
+ hsh { str? :bar, default: 'Baz', format: :date_time }
142
+ end
143
+ end
144
+
145
+ assert_cast(
146
+ { foo: { bar: '1990-01-13' } },
147
+ { foo: { bar: Date.new(1990, 1, 13) } }.with_indifferent_access
148
+ )
149
+
150
+ assert_cast(
151
+ { foo: { bar: '1990-01-13T10:00:00Z' } },
152
+ { foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) } }.with_indifferent_access
153
+ )
154
+ end
155
+
156
+ def test_with_generic_keywords
157
+ schema :one_of, title: 'oneOf schema',
158
+ description: 'oneOf schema holding generic keywords',
159
+ examples: [
160
+ 'foo'
161
+ ] do
162
+ str
163
+ int
164
+ end
165
+
166
+ assert_json({
167
+ oneOf: [
168
+ { type: :string },
169
+ { type: :integer }
170
+ ],
171
+ title: 'oneOf schema',
172
+ description: 'oneOf schema holding generic keywords',
173
+ examples: [
174
+ 'foo'
175
+ ]
176
+ })
177
+ end
178
+
179
+ def test_invalid_schema
180
+ assert_raises_with_message Exceptions::InvalidSchemaError,
181
+ 'Node "one_of" makes only sense with at least 2 items.' do
182
+ schema :one_of
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,351 @@
1
+ require 'test_helper'
2
+
3
+ module Schemacop
4
+ module V3
5
+ class ReferenceNodeTest < V3Test
6
+ def test_in_hash
7
+ context = Context.new
8
+ context.schema :MyString, :string
9
+ context.schema :MyInteger, :integer
10
+
11
+ Schemacop.with_context context do
12
+ schema do
13
+ ref? :foo, :MyString
14
+ ref? :int, :MyInteger
15
+ hsh? :bar do
16
+ ref? :foo, :MyString
17
+ hsh? :baz do
18
+ ref! :foo, :MyInteger
19
+ end
20
+ end
21
+ end
22
+
23
+ assert_validation({})
24
+ assert_validation(foo: 'String')
25
+ assert_validation(bar: { foo: 'String' })
26
+ assert_validation(bar: { foo: 'String', baz: { foo: 42 } })
27
+
28
+ assert_validation(foo: 42) do
29
+ error '/foo', 'Invalid type, expected "string".'
30
+ end
31
+ assert_validation(bar: { foo: 42 }) do
32
+ error '/bar/foo', 'Invalid type, expected "string".'
33
+ end
34
+ assert_validation(bar: { foo: 'String', baz: { foo: '42' } }) do
35
+ error '/bar/baz/foo', 'Invalid type, expected "integer".'
36
+ end
37
+
38
+ assert_json({
39
+ properties: {
40
+ foo: {
41
+ '$ref' => '#/definitions/MyString'
42
+ },
43
+ int: {
44
+ '$ref' => '#/definitions/MyInteger'
45
+ },
46
+ bar: {
47
+ properties: {
48
+ foo: {
49
+ '$ref' => '#/definitions/MyString'
50
+ },
51
+ baz: {
52
+ properties: {
53
+ foo: {
54
+ '$ref' => '#/definitions/MyInteger'
55
+ }
56
+ },
57
+ additionalProperties: false,
58
+ required: ['foo'],
59
+ type: :object
60
+ }
61
+ },
62
+ additionalProperties: false,
63
+ type: :object
64
+ }
65
+ },
66
+ additionalProperties: false,
67
+ type: :object
68
+ })
69
+ end
70
+ end
71
+
72
+ def test_schema_not_found
73
+ assert_raises_with_message RuntimeError, 'Schema "MyInteger" not found.' do
74
+ schema do
75
+ ref? :int, :MyInteger
76
+ end
77
+ assert_validation(int: 5)
78
+ end
79
+ end
80
+
81
+ def test_multiple_schemas
82
+ schema do
83
+ scm :Address do
84
+ str! :street
85
+ str! :zip_code
86
+ str! :location
87
+ str! :country
88
+ end
89
+
90
+ scm :Person do
91
+ str! :first_name
92
+ str! :last_name
93
+ str! :birthday, format: :date
94
+ end
95
+
96
+ ref! :person_info, :Person
97
+ ref! :shipping_address, :Address
98
+ ref! :billing_address, :Address
99
+ end
100
+
101
+ assert_json({
102
+ definitions: {
103
+ Address: {
104
+ properties: {
105
+ street: {
106
+ type: :string
107
+ },
108
+ zip_code: {
109
+ type: :string
110
+ },
111
+ location: {
112
+ type: :string
113
+ },
114
+ country: {
115
+ type: :string
116
+ }
117
+ },
118
+ additionalProperties: false,
119
+ required: %w[street zip_code location country],
120
+ type: :object
121
+ },
122
+ Person: {
123
+ properties: {
124
+ first_name: {
125
+ type: :string
126
+ },
127
+ last_name: {
128
+ type: :string
129
+ },
130
+ birthday: {
131
+ type: :string,
132
+ format: :date
133
+ }
134
+ },
135
+ additionalProperties: false,
136
+ required: %w[first_name last_name birthday],
137
+ type: :object
138
+ }
139
+ },
140
+ properties: {
141
+ person_info: {
142
+ '$ref' => '#/definitions/Person'
143
+ },
144
+ shipping_address: {
145
+ '$ref' => '#/definitions/Address'
146
+ },
147
+ billing_address: {
148
+ '$ref' => '#/definitions/Address'
149
+ }
150
+ },
151
+ type: :object,
152
+ additionalProperties: false,
153
+ required: %w[
154
+ person_info
155
+ shipping_address
156
+ billing_address
157
+ ]
158
+ })
159
+
160
+ assert_validation(nil)
161
+ assert_validation({
162
+ person_info: {
163
+ first_name: 'Joe',
164
+ last_name: 'Doe',
165
+ birthday: '1990-01-01'
166
+ },
167
+ billing_address: {
168
+ street: 'Badenerstrasse 530',
169
+ zip_code: '8048',
170
+ location: 'Zürich',
171
+ country: 'Switzerland'
172
+ },
173
+ shipping_address: {
174
+ street: 'Badenerstrasse 530',
175
+ zip_code: '8048',
176
+ location: 'Zürich',
177
+ country: 'Switzerland'
178
+ }
179
+ })
180
+
181
+ assert_validation({}) do
182
+ error '/person_info', 'Value must be given.'
183
+ error '/shipping_address', 'Value must be given.'
184
+ error '/billing_address', 'Value must be given.'
185
+ end
186
+ end
187
+
188
+ def test_nested_schemas
189
+ schema do
190
+ scm :User do
191
+ str! :first_name
192
+ str! :last_name
193
+ ary? :groups do
194
+ list :reference, path: :Group
195
+ end
196
+ end
197
+
198
+ scm :Group do
199
+ str! :name
200
+ end
201
+ end
202
+
203
+ assert_json({
204
+ additionalProperties: false,
205
+ definitions: {
206
+ User: {
207
+ properties: {
208
+ first_name: {
209
+ type: :string
210
+ },
211
+ last_name: {
212
+ type: :string
213
+ },
214
+ groups: {
215
+ type: :array,
216
+ items: {
217
+ '$ref' => '#/definitions/Group'
218
+ }
219
+ }
220
+ },
221
+ additionalProperties: false,
222
+ required: %w[first_name last_name],
223
+ type: :object
224
+ },
225
+ Group: {
226
+ properties: {
227
+ name: {
228
+ type: :string
229
+ }
230
+ },
231
+ additionalProperties: false,
232
+ required: ['name'],
233
+ type: :object
234
+ }
235
+ },
236
+ type: :object
237
+ })
238
+ end
239
+
240
+ def test_in_hash_recursion
241
+ schema do
242
+ scm :Node do
243
+ str! :name
244
+ ary? :children, min_items: 1 do
245
+ list :reference, path: :Node
246
+ end
247
+ end
248
+
249
+ ref? :node, :Node
250
+ end
251
+
252
+ assert_validation({})
253
+ assert_validation(node: { name: '1', children: [{ name: '1' }, { name: '2' }] })
254
+ assert_validation(
255
+ node: {
256
+ name: '1',
257
+ children: [
258
+ { name: '1.1' },
259
+ {
260
+ name: '1.2',
261
+ children: [
262
+ { name: '1.2.1' }
263
+ ]
264
+ }
265
+ ]
266
+ }
267
+ )
268
+
269
+ assert_validation(
270
+ node: {
271
+ name: '1',
272
+ children: [
273
+ { name: '1.1' },
274
+ {
275
+ name: '1.2',
276
+ children: [
277
+ { name: '1.2.1', children: [] }
278
+ ]
279
+ },
280
+ { name: '1.3', foo: :bar }
281
+ ]
282
+ }
283
+ ) do
284
+ error '/node/children/[1]/children/[0]/children', 'Array has 0 items but needs at least 1.'
285
+ error '/node/children/[2]', 'Obsolete property "foo".'
286
+ end
287
+ end
288
+
289
+ def test_external_schemas
290
+ context = Context.new
291
+
292
+ context.schema :Person do
293
+ str! :first_name
294
+ str! :last_name
295
+ ref? :info, :PersonInfo
296
+ end
297
+
298
+ context.schema :PersonInfo do
299
+ str! :born_at, format: :date
300
+ end
301
+
302
+ schema :reference, path: :Person
303
+
304
+ with_context context do
305
+ assert_validation(first_name: 'John', last_name: 'Doe')
306
+ assert_validation(first_name: 'John', last_name: 42) do
307
+ error '/last_name', 'Invalid type, expected "string".'
308
+ end
309
+ end
310
+
311
+ with_context context do
312
+ schema do
313
+ ref! :person, :Person
314
+ end
315
+
316
+ assert_validation(person: { first_name: 'John', last_name: 'Doe' })
317
+ assert_validation(person: { first_name: 'John', last_name: 'Doe', info: { born_at: '1990-01-13' } })
318
+ assert_validation(person: { first_name_x: 'John', last_name: 'Doe' }) do
319
+ error '/person', 'Obsolete property "first_name_x".'
320
+ error '/person/first_name', 'Value must be given.'
321
+ end
322
+ assert_validation(person: { first_name: 'John', last_name: 'Doe', info: { born_at: 'never' } }) do
323
+ error '/person/info/born_at', 'String does not match format "date".'
324
+ end
325
+ end
326
+ end
327
+
328
+ def test_defaults
329
+ schema do
330
+ scm :Person do
331
+ str? :foo, default: 'bar'
332
+ end
333
+ ref? :person, :Person, default: {}
334
+ end
335
+
336
+ assert_cast({}, { person: { foo: 'bar' } }.with_indifferent_access)
337
+ end
338
+
339
+ def test_casting
340
+ schema do
341
+ scm :Person do
342
+ str! :born_at, format: :date
343
+ end
344
+ ref? :person, :Person, default: {}
345
+ end
346
+
347
+ assert_cast({ person: { born_at: '1990-01-13' } }, { person: { born_at: Date.new(1990, 1, 13) } }.with_indifferent_access)
348
+ end
349
+ end
350
+ end
351
+ end