jsi 0.4.0 → 0.7.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.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +33 -0
- data/LICENSE.md +1 -1
- data/README.md +114 -42
- data/jsi.gemspec +14 -12
- data/lib/jsi/base/node.rb +183 -0
- data/lib/jsi/base.rb +388 -220
- data/lib/jsi/jsi_coder.rb +8 -7
- data/lib/jsi/metaschema.rb +0 -1
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +101 -0
- data/lib/jsi/metaschema_node.rb +159 -135
- data/lib/jsi/ptr.rb +303 -0
- data/lib/jsi/schema/application/child_application/contains.rb +25 -0
- data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
- data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
- data/lib/jsi/schema/application/child_application/draft07.rb +29 -0
- data/lib/jsi/schema/application/child_application/items.rb +18 -0
- data/lib/jsi/schema/application/child_application/properties.rb +25 -0
- data/lib/jsi/schema/application/child_application.rb +38 -0
- data/lib/jsi/schema/application/draft04.rb +8 -0
- data/lib/jsi/schema/application/draft06.rb +8 -0
- data/lib/jsi/schema/application/draft07.rb +8 -0
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
- data/lib/jsi/schema/application/inplace_application/draft04.rb +26 -0
- data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
- data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -0
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
- data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
- data/lib/jsi/schema/application/inplace_application/someof.rb +44 -0
- data/lib/jsi/schema/application/inplace_application.rb +41 -0
- data/lib/jsi/schema/application.rb +12 -0
- data/lib/jsi/schema/draft04.rb +14 -0
- data/lib/jsi/schema/draft06.rb +14 -0
- data/lib/jsi/schema/draft07.rb +14 -0
- data/lib/jsi/schema/issue.rb +36 -0
- data/lib/jsi/schema/ref.rb +160 -0
- data/lib/jsi/schema/schema_ancestor_node.rb +113 -0
- data/lib/jsi/schema/validation/array.rb +69 -0
- data/lib/jsi/schema/validation/const.rb +20 -0
- data/lib/jsi/schema/validation/contains.rb +25 -0
- data/lib/jsi/schema/validation/core.rb +39 -0
- data/lib/jsi/schema/validation/dependencies.rb +49 -0
- data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
- data/lib/jsi/schema/validation/draft04.rb +112 -0
- data/lib/jsi/schema/validation/draft06.rb +122 -0
- data/lib/jsi/schema/validation/draft07.rb +159 -0
- data/lib/jsi/schema/validation/enum.rb +25 -0
- data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
- data/lib/jsi/schema/validation/items.rb +54 -0
- data/lib/jsi/schema/validation/not.rb +20 -0
- data/lib/jsi/schema/validation/numeric.rb +121 -0
- data/lib/jsi/schema/validation/object.rb +45 -0
- data/lib/jsi/schema/validation/pattern.rb +34 -0
- data/lib/jsi/schema/validation/properties.rb +101 -0
- data/lib/jsi/schema/validation/property_names.rb +32 -0
- data/lib/jsi/schema/validation/ref.rb +40 -0
- data/lib/jsi/schema/validation/required.rb +27 -0
- data/lib/jsi/schema/validation/someof.rb +90 -0
- data/lib/jsi/schema/validation/string.rb +47 -0
- data/lib/jsi/schema/validation/type.rb +49 -0
- data/lib/jsi/schema/validation.rb +51 -0
- data/lib/jsi/schema.rb +508 -149
- data/lib/jsi/schema_classes.rb +199 -59
- data/lib/jsi/schema_registry.rb +151 -0
- data/lib/jsi/schema_set.rb +181 -0
- data/lib/jsi/simple_wrap.rb +23 -4
- data/lib/jsi/util/private/attr_struct.rb +127 -0
- data/lib/jsi/util/private.rb +204 -0
- data/lib/jsi/util/typelike.rb +229 -0
- data/lib/jsi/util.rb +89 -53
- data/lib/jsi/validation/error.rb +34 -0
- data/lib/jsi/validation/result.rb +210 -0
- data/lib/jsi/validation.rb +15 -0
- data/lib/jsi/version.rb +3 -1
- data/lib/jsi.rb +44 -14
- data/lib/schemas/json-schema.org/draft-04/schema.rb +10 -3
- data/lib/schemas/json-schema.org/draft-06/schema.rb +10 -3
- data/lib/schemas/json-schema.org/draft-07/schema.rb +14 -0
- data/readme.rb +138 -0
- data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
- data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
- data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
- metadata +75 -122
- data/.simplecov +0 -3
- data/Rakefile.rb +0 -9
- data/lib/jsi/base/to_rb.rb +0 -128
- data/lib/jsi/json/node.rb +0 -203
- data/lib/jsi/json/pointer.rb +0 -419
- data/lib/jsi/json-schema-fragments.rb +0 -61
- data/lib/jsi/json.rb +0 -10
- data/lib/jsi/pathed_node.rb +0 -118
- data/lib/jsi/typelike_modules.rb +0 -240
- data/resources/icons/AGPL-3.0.png +0 -0
- data/test/base_array_test.rb +0 -323
- data/test/base_hash_test.rb +0 -337
- data/test/base_test.rb +0 -486
- data/test/jsi_coder_test.rb +0 -85
- data/test/jsi_json_arraynode_test.rb +0 -150
- data/test/jsi_json_hashnode_test.rb +0 -132
- data/test/jsi_json_node_test.rb +0 -257
- data/test/jsi_json_pointer_test.rb +0 -102
- data/test/jsi_test.rb +0 -11
- data/test/jsi_typelike_as_json_test.rb +0 -53
- data/test/metaschema_node_test.rb +0 -19
- data/test/schema_module_test.rb +0 -21
- data/test/schema_test.rb +0 -208
- data/test/spreedly_openapi_test.rb +0 -8
- data/test/test_helper.rb +0 -97
- data/test/util_test.rb +0 -62
data/test/base_test.rb
DELETED
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
require_relative 'test_helper'
|
|
2
|
-
|
|
3
|
-
NamedSchemaInstance = JSI::Schema.new({id: 'https://schemas.jsi.unth.net/test/base/named_schema'}).jsi_schema_class
|
|
4
|
-
|
|
5
|
-
# hitting .tap(&:name) causes JSI to assign a constant name from the ID,
|
|
6
|
-
# meaning the name NamedSchemaInstanceTwo is not known.
|
|
7
|
-
NamedSchemaInstanceTwo = JSI::Schema.new({id: 'https://schemas.jsi.unth.net/test/base/named_schema_two'}).jsi_schema_class.tap(&:name)
|
|
8
|
-
|
|
9
|
-
describe JSI::Base do
|
|
10
|
-
let(:schema_content) { {} }
|
|
11
|
-
let(:schema) { JSI::Schema.new(schema_content) }
|
|
12
|
-
let(:instance) { {} }
|
|
13
|
-
let(:subject) { schema.new_jsi(instance) }
|
|
14
|
-
describe 'class .inspect' do
|
|
15
|
-
it 'is the same as Class#inspect on the base' do
|
|
16
|
-
assert_equal('JSI::Base', JSI::Base.inspect)
|
|
17
|
-
end
|
|
18
|
-
it 'is (JSI Schema Class) for generated subclass without id' do
|
|
19
|
-
assert_equal("(JSI Schema Class: #)", subject.class.inspect)
|
|
20
|
-
end
|
|
21
|
-
describe 'with schema id' do
|
|
22
|
-
let(:schema_content) { {'id' => 'https://jsi/foo'} }
|
|
23
|
-
it 'is (JSI Schema Class: ...) for generated subclass with id' do
|
|
24
|
-
assert_equal("(JSI Schema Class: https://jsi/foo#)", subject.class.inspect)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
it 'is the constant name plus id for a class assigned to a constant' do
|
|
28
|
-
assert_equal(%q(NamedSchemaInstance (https://schemas.jsi.unth.net/test/base/named_schema#)), NamedSchemaInstance.inspect)
|
|
29
|
-
end
|
|
30
|
-
it 'is not the constant name when the constant name has been generated from the schema_id' do
|
|
31
|
-
assert_equal("JSI::SchemaClasses::Xhttps___schemas_jsi_unth_net_test_base_named_schema_two_", NamedSchemaInstanceTwo.name)
|
|
32
|
-
assert_equal("(JSI Schema Class: https://schemas.jsi.unth.net/test/base/named_schema_two#)", NamedSchemaInstanceTwo.inspect)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
describe 'class name' do
|
|
36
|
-
let(:schema_content) { {'id' => 'https://jsi/BaseTest'} }
|
|
37
|
-
it 'generates a class name from schema_id' do
|
|
38
|
-
assert_equal('JSI::SchemaClasses::Xhttps___jsi_BaseTest_', subject.class.name)
|
|
39
|
-
end
|
|
40
|
-
it 'uses an existing name' do
|
|
41
|
-
assert_equal('NamedSchemaInstance', NamedSchemaInstance.name)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
describe 'class for schema .jsi_class_schemas' do
|
|
45
|
-
it '.jsi_class_schemas' do
|
|
46
|
-
assert_equal(Set.new << schema, schema.jsi_schema_class.jsi_class_schemas)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
describe 'module for schema .inspect' do
|
|
50
|
-
it '.inspect' do
|
|
51
|
-
assert_equal("(JSI Schema Module: #)", JSI::SchemaClasses.module_for_schema(schema).inspect)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
describe 'module for schema .schema' do
|
|
55
|
-
it '.schema' do
|
|
56
|
-
assert_equal(schema, JSI::SchemaClasses.module_for_schema(schema).schema)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
describe '.class_for_schemas' do
|
|
60
|
-
it 'returns a class from a schema' do
|
|
61
|
-
class_for_schema = JSI.class_for_schemas([schema])
|
|
62
|
-
# same class every time
|
|
63
|
-
assert_equal(JSI.class_for_schemas([schema]), class_for_schema)
|
|
64
|
-
assert_operator(class_for_schema, :<, JSI::Base)
|
|
65
|
-
end
|
|
66
|
-
it 'returns the same class from a hash' do
|
|
67
|
-
assert_equal(JSI.class_for_schemas([schema]), JSI.class_for_schemas([schema_content]))
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
describe 'JSI::SchemaClasses.module_for_schema' do
|
|
71
|
-
it 'returns a module from a schema' do
|
|
72
|
-
module_for_schema = JSI::SchemaClasses.module_for_schema(schema)
|
|
73
|
-
# same module every time
|
|
74
|
-
assert_equal(JSI::SchemaClasses.module_for_schema(schema), module_for_schema)
|
|
75
|
-
end
|
|
76
|
-
it 'returns a module from a hash' do
|
|
77
|
-
assert_equal(JSI::SchemaClasses.module_for_schema(schema), JSI::SchemaClasses.module_for_schema(schema.jsi_instance))
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
describe 'initialization' do
|
|
81
|
-
describe 'on Base' do
|
|
82
|
-
it 'errors' do
|
|
83
|
-
err = assert_raises(TypeError) { JSI::Base.new({}) }
|
|
84
|
-
assert_equal('cannot instantiate JSI::Base which has no method #jsi_schemas. it is recommended to instantiate JSIs from a schema using JSI::Schema#new_jsi.', err.message)
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
describe 'nil' do
|
|
88
|
-
let(:instance) { nil }
|
|
89
|
-
it 'initializes with nil instance' do
|
|
90
|
-
assert_equal(nil, subject.jsi_instance)
|
|
91
|
-
assert(!subject.respond_to?(:to_ary))
|
|
92
|
-
assert(!subject.respond_to?(:to_hash))
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
describe 'arbitrary instance' do
|
|
96
|
-
let(:instance) { Object.new }
|
|
97
|
-
it 'initializes' do
|
|
98
|
-
assert_equal(instance, subject.jsi_instance)
|
|
99
|
-
assert(!subject.respond_to?(:to_ary))
|
|
100
|
-
assert(!subject.respond_to?(:to_hash))
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
describe 'hash' do
|
|
104
|
-
let(:instance) { {'foo' => 'bar'} }
|
|
105
|
-
let(:schema_content) { {'type' => 'object'} }
|
|
106
|
-
it 'initializes' do
|
|
107
|
-
assert_equal({'foo' => 'bar'}, subject.jsi_instance)
|
|
108
|
-
assert(!subject.respond_to?(:to_ary))
|
|
109
|
-
assert(subject.respond_to?(:to_hash))
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
describe 'JSI::JSON::HashNode' do
|
|
113
|
-
let(:instance) { JSI::JSON::HashNode.new({'foo' => 'bar'}, JSI::JSON::Pointer.new([])) }
|
|
114
|
-
let(:schema_content) { {'type' => 'object'} }
|
|
115
|
-
it 'initializes' do
|
|
116
|
-
assert_equal(JSI::JSON::HashNode.new({'foo' => 'bar'}, JSI::JSON::Pointer.new([])), subject.jsi_instance)
|
|
117
|
-
assert(!subject.respond_to?(:to_ary))
|
|
118
|
-
assert(subject.respond_to?(:to_hash))
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
describe 'array' do
|
|
122
|
-
let(:instance) { ['foo'] }
|
|
123
|
-
let(:schema_content) { {'type' => 'array'} }
|
|
124
|
-
it 'initializes' do
|
|
125
|
-
assert_equal(['foo'], subject.jsi_instance)
|
|
126
|
-
assert(subject.respond_to?(:to_ary))
|
|
127
|
-
assert(!subject.respond_to?(:to_hash))
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
describe 'JSI::JSON::ArrayNode' do
|
|
131
|
-
let(:instance) { JSI::JSON::ArrayNode.new(['foo'], JSI::JSON::Pointer.new([])) }
|
|
132
|
-
let(:schema_content) { {'type' => 'array'} }
|
|
133
|
-
it 'initializes' do
|
|
134
|
-
assert_equal(JSI::JSON::ArrayNode.new(['foo'], JSI::JSON::Pointer.new([])), subject.jsi_instance)
|
|
135
|
-
assert(subject.respond_to?(:to_ary))
|
|
136
|
-
assert(!subject.respond_to?(:to_hash))
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
describe 'another JSI::Base invalid' do
|
|
140
|
-
let(:schema_content) { {'type' => 'object'} }
|
|
141
|
-
let(:instance) { schema.new_jsi({'foo' => 'bar'}) }
|
|
142
|
-
it 'initializes with an error' do
|
|
143
|
-
err = assert_raises(TypeError) { subject }
|
|
144
|
-
assert_equal("assigning another JSI::Base instance to a (JSI Schema Class: #) instance is incorrect. received: \#{<JSI> \"foo\" => \"bar\"}", err.message)
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
describe 'Schema invalid' do
|
|
148
|
-
let(:instance) { JSI::Schema.new({}) }
|
|
149
|
-
it 'initializes with an error' do
|
|
150
|
-
err = assert_raises(TypeError) { subject }
|
|
151
|
-
assert_equal("assigning a schema to a (JSI Schema Class: #) instance is incorrect. received: \#{<JSI (JSI::JSONSchemaOrgDraft06) Schema>}", err.message)
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
describe '#parent_jsis, #parent_jsi' do
|
|
156
|
-
let(:schema_content) { {'properties' => {'foo' => {'properties' => {'bar' => {'properties' => {'baz' => {}}}}}}} }
|
|
157
|
-
let(:instance) { {'foo' => {'bar' => {'baz' => {}}}} }
|
|
158
|
-
describe 'no parent_jsis' do
|
|
159
|
-
it 'has none' do
|
|
160
|
-
assert_equal([], subject.parents)
|
|
161
|
-
assert_equal([], subject.parent_jsis)
|
|
162
|
-
assert_equal(nil, subject.parent)
|
|
163
|
-
assert_equal(nil, subject.parent_jsi)
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
describe 'one parent_jsi' do
|
|
167
|
-
it 'has one' do
|
|
168
|
-
assert_equal([subject], subject.foo.parents)
|
|
169
|
-
assert_equal([subject], subject.foo.parent_jsis)
|
|
170
|
-
assert_equal(subject, subject.foo.parent)
|
|
171
|
-
assert_equal(subject, subject.foo.parent_jsi)
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
describe 'more parent_jsis' do
|
|
175
|
-
it 'has more' do
|
|
176
|
-
assert_equal([subject.foo.bar, subject.foo, subject], subject.foo.bar.baz.parents)
|
|
177
|
-
assert_equal([subject.foo.bar, subject.foo, subject], subject.foo.bar.baz.parent_jsis)
|
|
178
|
-
assert_equal(subject.foo.bar, subject.foo.bar.baz.parent)
|
|
179
|
-
assert_equal(subject.foo.bar, subject.foo.bar.baz.parent_jsi)
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
describe '#each, Enumerable methods' do
|
|
184
|
-
let(:instance) { 'a string' }
|
|
185
|
-
it "raises NoMethodError calling each or Enumerable methods" do
|
|
186
|
-
assert_raises(NoMethodError) { subject.each { nil } }
|
|
187
|
-
assert_raises(NoMethodError) { subject.map { nil } }
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
describe '#modified_copy' do
|
|
191
|
-
describe 'with an instance that does not have #modified_copy' do
|
|
192
|
-
let(:instance) { Object.new }
|
|
193
|
-
it 'yields the instance to modify' do
|
|
194
|
-
new_instance = Object.new
|
|
195
|
-
modified = subject.modified_copy do |o|
|
|
196
|
-
assert_equal(instance, o)
|
|
197
|
-
new_instance
|
|
198
|
-
end
|
|
199
|
-
assert_equal(new_instance, modified.jsi_instance)
|
|
200
|
-
assert_equal(instance, subject.jsi_instance)
|
|
201
|
-
refute_equal(instance, modified)
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
describe 'with an instance that does have #modified_copy' do
|
|
205
|
-
it 'yields the instance to modify' do
|
|
206
|
-
modified = subject.modified_copy do |o|
|
|
207
|
-
assert_equal({}, o)
|
|
208
|
-
{'a' => 'b'}
|
|
209
|
-
end
|
|
210
|
-
assert_equal({'a' => 'b'}, modified.jsi_instance)
|
|
211
|
-
assert_equal({}, subject.jsi_instance)
|
|
212
|
-
refute_equal(instance, modified)
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
describe 'no modification' do
|
|
216
|
-
it 'yields the instance to modify' do
|
|
217
|
-
modified = subject.modified_copy { |o| o }
|
|
218
|
-
# this doesn't really need to be tested but ... whatever
|
|
219
|
-
assert_equal(subject.jsi_instance.object_id, modified.jsi_instance.object_id)
|
|
220
|
-
assert_equal(subject, modified)
|
|
221
|
-
refute_equal(subject.object_id, modified.object_id)
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
describe 'resulting in a different type' do
|
|
225
|
-
let(:schema_content) { {'type' => 'object'} }
|
|
226
|
-
it 'works' do
|
|
227
|
-
# I'm not really sure the best thing to do here, but this is how it is for now. this is subject to change.
|
|
228
|
-
modified = subject.modified_copy do |o|
|
|
229
|
-
o.to_s
|
|
230
|
-
end
|
|
231
|
-
assert_equal('{}', modified.jsi_instance)
|
|
232
|
-
assert_equal({}, subject.jsi_instance)
|
|
233
|
-
refute_equal(instance, modified)
|
|
234
|
-
# interesting side effect
|
|
235
|
-
assert(subject.respond_to?(:to_hash))
|
|
236
|
-
assert(!modified.respond_to?(:to_hash))
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
describe 'validation' do
|
|
241
|
-
describe 'without errors' do
|
|
242
|
-
it '#fully_validate' do
|
|
243
|
-
assert_equal([], subject.fully_validate)
|
|
244
|
-
end
|
|
245
|
-
it '#validate' do
|
|
246
|
-
assert_equal(true, subject.validate)
|
|
247
|
-
end
|
|
248
|
-
it '#validate!' do
|
|
249
|
-
assert_equal(true, subject.validate!)
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
describe 'with errors' do
|
|
253
|
-
let(:schema_content) {
|
|
254
|
-
{
|
|
255
|
-
'id' => 'https://schemas.jsi.unth.net/test/JSI::Base::validation::with errors',
|
|
256
|
-
'type' => 'object',
|
|
257
|
-
'properties' => {
|
|
258
|
-
'some_number' => {
|
|
259
|
-
'type' => 'number'
|
|
260
|
-
},
|
|
261
|
-
'a_required_property' => {
|
|
262
|
-
'type' => 'string'
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
let(:instance) { "this is a string" }
|
|
268
|
-
|
|
269
|
-
it '#validate' do
|
|
270
|
-
assert_equal(false, subject.validate)
|
|
271
|
-
end
|
|
272
|
-
it '#validate!' do
|
|
273
|
-
assert_raises JSON::Schema::ValidationError do
|
|
274
|
-
subject.validate!
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
describe 'fully_validate' do
|
|
278
|
-
it '#fully_validate ' do
|
|
279
|
-
assert_equal(["The property '#/' of type string did not match the following type: object in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::with errors"], subject.fully_validate)
|
|
280
|
-
end
|
|
281
|
-
it '#fully_validate :errors_as_objects' do
|
|
282
|
-
expected = [
|
|
283
|
-
{
|
|
284
|
-
:schema => Addressable::URI.parse('https://schemas.jsi.unth.net/test/JSI::Base::validation::with errors'),
|
|
285
|
-
:fragment => "#/",
|
|
286
|
-
:message => "The property '#/' of type string did not match the following type: object in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::with errors",
|
|
287
|
-
:failed_attribute=>"TypeV4"
|
|
288
|
-
}
|
|
289
|
-
]
|
|
290
|
-
assert_equal(expected, subject.fully_validate(:errors_as_objects => true))
|
|
291
|
-
end
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
describe 'at a depth' do
|
|
295
|
-
let(:schema_content) do
|
|
296
|
-
{
|
|
297
|
-
'id' => 'https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth',
|
|
298
|
-
'description' => 'hash schema',
|
|
299
|
-
'type' => 'object',
|
|
300
|
-
'properties' => {
|
|
301
|
-
'foo' => {'type' => 'object'},
|
|
302
|
-
'bar' => {},
|
|
303
|
-
'baz' => {'type' => 'array'},
|
|
304
|
-
},
|
|
305
|
-
'additionalProperties' => {'not' => {}},
|
|
306
|
-
}
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
describe 'without errors' do
|
|
310
|
-
let(:instance) { {'foo' => {'x' => 'y'}, 'bar' => [9], 'baz' => [true]} }
|
|
311
|
-
|
|
312
|
-
it '#fully_validate' do
|
|
313
|
-
assert_equal([], subject.foo.fully_validate)
|
|
314
|
-
assert_equal([], subject.bar.fully_validate)
|
|
315
|
-
end
|
|
316
|
-
it '#validate' do
|
|
317
|
-
assert_equal(true, subject.foo.validate)
|
|
318
|
-
assert_equal(true, subject.bar.validate)
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
describe 'with errors' do
|
|
322
|
-
let(:instance) { {'foo' => [true], 'bar' => [9], 'baz' => {'x' => 'y'}, 'more' => {}} }
|
|
323
|
-
|
|
324
|
-
it '#fully_validate' do
|
|
325
|
-
assert_equal(["The property '#/' of type array did not match the following type: object in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth"], subject.foo.fully_validate)
|
|
326
|
-
assert_equal([], subject.bar.fully_validate)
|
|
327
|
-
assert_equal(["The property '#/' of type object did not match the following type: array in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth"], subject.baz.fully_validate)
|
|
328
|
-
assert_equal(["The property '#/' of type object matched the disallowed schema in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth"], subject['more'].fully_validate)
|
|
329
|
-
assert_equal(["The property '#/foo' of type array did not match the following type: object in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth", "The property '#/baz' of type object did not match the following type: array in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth", "The property '#/more' of type object matched the disallowed schema in schema https://schemas.jsi.unth.net/test/JSI::Base::validation::at a depth"], subject.fully_validate)
|
|
330
|
-
end
|
|
331
|
-
it '#validate' do
|
|
332
|
-
assert_equal(false, subject.foo.validate)
|
|
333
|
-
assert_equal(true, subject.bar.validate)
|
|
334
|
-
assert_equal(false, subject.baz.validate)
|
|
335
|
-
assert_equal(false, subject['more'].validate)
|
|
336
|
-
assert_equal(false, subject.validate)
|
|
337
|
-
end
|
|
338
|
-
end
|
|
339
|
-
end
|
|
340
|
-
end
|
|
341
|
-
describe 'property accessors' do
|
|
342
|
-
let(:schema_content) do
|
|
343
|
-
{
|
|
344
|
-
'type' => 'object',
|
|
345
|
-
'properties' => {
|
|
346
|
-
'foo' => {'type' => 'object'},
|
|
347
|
-
'bar' => {'type' => 'array'},
|
|
348
|
-
'baz' => {},
|
|
349
|
-
},
|
|
350
|
-
}
|
|
351
|
-
end
|
|
352
|
-
let(:instance) do
|
|
353
|
-
{'foo' => {'x' => 'y'}, 'bar' => [3.14159], 'baz' => true, 'qux' => []}
|
|
354
|
-
end
|
|
355
|
-
describe 'readers' do
|
|
356
|
-
it 'reads attributes described as properties' do
|
|
357
|
-
assert_equal({'x' => 'y'}, subject.foo.as_json)
|
|
358
|
-
assert_is_a(schema.properties['foo'].jsi_schema_module, subject.foo)
|
|
359
|
-
assert_respond_to(subject.foo, :to_hash)
|
|
360
|
-
refute_respond_to(subject.foo, :to_ary)
|
|
361
|
-
assert_equal([3.14159], subject.bar.as_json)
|
|
362
|
-
assert_is_a(schema.properties['bar'].jsi_schema_module, subject.bar)
|
|
363
|
-
refute_respond_to(subject.bar, :to_hash)
|
|
364
|
-
assert_respond_to(subject.bar, :to_ary)
|
|
365
|
-
assert_equal(true, subject.baz)
|
|
366
|
-
refute_respond_to(subject.baz, :to_hash)
|
|
367
|
-
refute_respond_to(subject.baz, :to_ary)
|
|
368
|
-
refute_respond_to(subject, :qux)
|
|
369
|
-
end
|
|
370
|
-
describe 'when the instance is not hashlike' do
|
|
371
|
-
let(:instance) { nil }
|
|
372
|
-
it 'errors' do
|
|
373
|
-
err = assert_raises(JSI::Base::CannotSubscriptError) { subject.foo }
|
|
374
|
-
assert_equal(%q(cannot subcript (using token: "foo") from instance: nil), err.message)
|
|
375
|
-
end
|
|
376
|
-
end
|
|
377
|
-
describe 'properties with the same names as instance methods' do
|
|
378
|
-
let(:schema_content) do
|
|
379
|
-
{
|
|
380
|
-
'type' => 'object',
|
|
381
|
-
'properties' => {
|
|
382
|
-
'foo' => {}, # not an instance method
|
|
383
|
-
'initialize' => {}, # Base
|
|
384
|
-
'inspect' => {}, # Base
|
|
385
|
-
'pretty_inspect' => {}, # Kernel
|
|
386
|
-
'as_json' => {}, # Base::OverrideFromExtensions, extended on initialization
|
|
387
|
-
'each' => {}, # PathedHashNode / PathedArrayNode
|
|
388
|
-
'instance_exec' => {}, # BasicObject
|
|
389
|
-
'jsi_instance' => {}, # Base
|
|
390
|
-
'jsi_schemas' => {}, # module_for_schema singleton definition
|
|
391
|
-
},
|
|
392
|
-
}
|
|
393
|
-
end
|
|
394
|
-
let(:instance) do
|
|
395
|
-
{
|
|
396
|
-
'foo' => 'bar',
|
|
397
|
-
'initialize' => 'hi',
|
|
398
|
-
'inspect' => 'hi',
|
|
399
|
-
'pretty_inspect' => 'hi',
|
|
400
|
-
'as_json' => 'hi',
|
|
401
|
-
'each' => 'hi',
|
|
402
|
-
'instance_exec' => 'hi',
|
|
403
|
-
'jsi_instance' => 'hi',
|
|
404
|
-
'jsi_schemas' => 'hi',
|
|
405
|
-
}
|
|
406
|
-
end
|
|
407
|
-
it 'does not define readers' do
|
|
408
|
-
assert_equal('bar', subject.foo) # this one is defined
|
|
409
|
-
|
|
410
|
-
assert_equal(JSI::Base, subject.method(:initialize).owner)
|
|
411
|
-
assert_equal('hi', subject['initialize'])
|
|
412
|
-
assert_equal(%q(#{<JSI> "foo" => "bar", "initialize" => "hi", "inspect" => "hi", "pretty_inspect" => "hi", "as_json" => "hi", "each" => "hi", "instance_exec" => "hi", "jsi_instance" => "hi", "jsi_schemas" => "hi"}), subject.inspect)
|
|
413
|
-
assert_equal('hi', subject['inspect'])
|
|
414
|
-
assert_equal(%Q(\#{<JSI>\n "foo" => "bar",\n "initialize" => "hi",\n "inspect" => "hi",\n "pretty_inspect" => "hi",\n "as_json" => "hi",\n "each" => "hi",\n "instance_exec" => "hi",\n "jsi_instance" => "hi",\n "jsi_schemas" => "hi"\n}\n), subject.pretty_inspect)
|
|
415
|
-
assert_equal(instance, subject.as_json)
|
|
416
|
-
assert_equal(subject, subject.each { })
|
|
417
|
-
assert_equal(2, subject.instance_exec { 2 })
|
|
418
|
-
assert_equal(instance, subject.jsi_instance)
|
|
419
|
-
assert_equal(Set.new << schema, subject.jsi_schemas)
|
|
420
|
-
end
|
|
421
|
-
end
|
|
422
|
-
end
|
|
423
|
-
describe 'writers' do
|
|
424
|
-
it 'writes attributes described as properties' do
|
|
425
|
-
orig_foo = subject.foo
|
|
426
|
-
|
|
427
|
-
subject.foo = {'y' => 'z'}
|
|
428
|
-
|
|
429
|
-
assert_equal({'y' => 'z'}, subject.foo.as_json)
|
|
430
|
-
assert_is_a(schema.properties['foo'].jsi_schema_module, orig_foo)
|
|
431
|
-
assert_is_a(schema.properties['foo'].jsi_schema_module, subject.foo)
|
|
432
|
-
end
|
|
433
|
-
it 'modifies the instance, visible to other references to the same instance' do
|
|
434
|
-
orig_instance = subject.jsi_instance
|
|
435
|
-
|
|
436
|
-
subject.foo = {'y' => 'z'}
|
|
437
|
-
|
|
438
|
-
assert_equal(orig_instance, subject.jsi_instance)
|
|
439
|
-
assert_equal({'y' => 'z'}, orig_instance['foo'])
|
|
440
|
-
assert_equal({'y' => 'z'}, subject.jsi_instance['foo'])
|
|
441
|
-
assert_equal(orig_instance.class, subject.jsi_instance.class)
|
|
442
|
-
end
|
|
443
|
-
describe 'when the instance is not hashlike' do
|
|
444
|
-
let(:instance) { nil }
|
|
445
|
-
it 'errors' do
|
|
446
|
-
err = assert_raises(NoMethodError) { subject.foo = 0 }
|
|
447
|
-
assert_equal('cannot assign subcript (using token: "foo") to instance: nil', err.message)
|
|
448
|
-
end
|
|
449
|
-
end
|
|
450
|
-
end
|
|
451
|
-
end
|
|
452
|
-
describe '#inspect' do
|
|
453
|
-
# if the instance is hash-like, #inspect gets overridden
|
|
454
|
-
let(:instance) { Object.new }
|
|
455
|
-
it 'inspects' do
|
|
456
|
-
assert_match(%r(\A\#<JSI\ \#<Object:[^<>]*>>\z), subject.inspect)
|
|
457
|
-
end
|
|
458
|
-
end
|
|
459
|
-
describe '#pretty_print' do
|
|
460
|
-
# if the instance is hash-like, #pretty_print gets overridden
|
|
461
|
-
let(:instance) { Object.new }
|
|
462
|
-
it 'pretty_prints' do
|
|
463
|
-
assert_match(%r(\A\#<JSI\ \#<Object:[^<>]*>>\z), subject.pretty_inspect.chomp)
|
|
464
|
-
end
|
|
465
|
-
end
|
|
466
|
-
describe '#as_json' do
|
|
467
|
-
it '#as_json' do
|
|
468
|
-
assert_equal({'a' => 'b'}, JSI::Schema.new({}).new_jsi({'a' => 'b'}).as_json)
|
|
469
|
-
assert_equal({'a' => 'b'}, JSI::Schema.new({}).new_jsi(JSI::JSON::Node.new_doc({'a' => 'b'})).as_json)
|
|
470
|
-
assert_equal({'a' => 'b'}, JSI::Schema.new({'type' => 'object'}).new_jsi(JSI::JSON::Node.new_doc({'a' => 'b'})).as_json)
|
|
471
|
-
assert_equal(['a', 'b'], JSI::Schema.new({'type' => 'array'}).new_jsi(JSI::JSON::Node.new_doc(['a', 'b'])).as_json)
|
|
472
|
-
assert_equal(['a'], JSI::Schema.new({}).new_jsi(['a']).as_json(some_option: true))
|
|
473
|
-
end
|
|
474
|
-
end
|
|
475
|
-
describe 'equality between different classes of JSI::Base subclasses' do
|
|
476
|
-
let(:subject_subclass) { Class.new(schema.jsi_schema_class).new(instance) }
|
|
477
|
-
|
|
478
|
-
it 'considers a Base subclass (class_for_schema) and subsubclass to be equal with the same instance' do
|
|
479
|
-
assert_equal(subject.hash, subject_subclass.hash)
|
|
480
|
-
assert(subject == subject_subclass)
|
|
481
|
-
assert(subject_subclass == subject)
|
|
482
|
-
assert(subject.eql?(subject_subclass))
|
|
483
|
-
assert(subject_subclass.eql?(subject))
|
|
484
|
-
end
|
|
485
|
-
end
|
|
486
|
-
end
|
data/test/jsi_coder_test.rb
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
require_relative 'test_helper'
|
|
2
|
-
|
|
3
|
-
describe JSI::JSICoder do
|
|
4
|
-
let(:schema_content) do
|
|
5
|
-
{properties: {foo: {}, bar: {}}}
|
|
6
|
-
end
|
|
7
|
-
let(:schema) { JSI::Schema.new(schema_content) }
|
|
8
|
-
let(:options) { {} }
|
|
9
|
-
let(:schema_instance_json_coder) { JSI::JSICoder.new(schema, options) }
|
|
10
|
-
describe 'json' do
|
|
11
|
-
describe 'load' do
|
|
12
|
-
it 'loads nil' do
|
|
13
|
-
assert_nil(schema_instance_json_coder.load(nil))
|
|
14
|
-
end
|
|
15
|
-
it 'loads a hash' do
|
|
16
|
-
assert_equal(schema.new_jsi('foo' => 'bar'), schema_instance_json_coder.load({"foo" => "bar"}))
|
|
17
|
-
end
|
|
18
|
-
it 'loads something else' do
|
|
19
|
-
assert_equal(schema.new_jsi([[]]), schema_instance_json_coder.load([[]]))
|
|
20
|
-
end
|
|
21
|
-
describe 'array' do
|
|
22
|
-
let(:options) { {array: true} }
|
|
23
|
-
it 'loads an array of hashes' do
|
|
24
|
-
data = [{"foo" => "bar"}, {"foo" => "baz"}]
|
|
25
|
-
assert_equal([schema.new_jsi('foo' => 'bar'), schema.new_jsi('foo' => 'baz')], schema_instance_json_coder.load(data))
|
|
26
|
-
end
|
|
27
|
-
it 'loads an empty array' do
|
|
28
|
-
assert_equal([], schema_instance_json_coder.load([]))
|
|
29
|
-
end
|
|
30
|
-
it 'loads a not an array' do
|
|
31
|
-
assert_raises(TypeError) do
|
|
32
|
-
schema_instance_json_coder.load(Object.new)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
describe 'array schema' do
|
|
37
|
-
let(:schema_content) { {items: {properties: {foo: {}, bar: {}}}} }
|
|
38
|
-
it 'loads an array of hashes' do
|
|
39
|
-
data = [{"foo" => "bar"}, {"foo" => "baz"}]
|
|
40
|
-
assert_equal(schema.new_jsi([{'foo' => 'bar'}, {'foo' => 'baz'}]), schema_instance_json_coder.load(data))
|
|
41
|
-
end
|
|
42
|
-
it 'loads an empty array' do
|
|
43
|
-
assert_equal(schema.new_jsi([]), schema_instance_json_coder.load([]))
|
|
44
|
-
end
|
|
45
|
-
it 'loads a not an array' do
|
|
46
|
-
instance = Object.new
|
|
47
|
-
assert_equal(schema.new_jsi(instance), schema_instance_json_coder.load(instance))
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
describe 'dump' do
|
|
52
|
-
it 'dumps nil' do
|
|
53
|
-
assert_nil(schema_instance_json_coder.dump(nil))
|
|
54
|
-
end
|
|
55
|
-
it 'dumps a schema_instance_class' do
|
|
56
|
-
assert_equal({"foo" => "x", "bar" => "y"}, schema_instance_json_coder.dump(schema.new_jsi(foo: 'x', bar: 'y')))
|
|
57
|
-
end
|
|
58
|
-
it 'dumps something else' do
|
|
59
|
-
assert_raises(TypeError) do
|
|
60
|
-
schema_instance_json_coder.dump(Object.new)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
it 'dumps some of the keys of a schema_instance_class after loading in a partial one' do
|
|
64
|
-
schema_instance_class = schema_instance_json_coder.load({'foo' => 'who'})
|
|
65
|
-
assert_equal({'foo' => 'who'}, schema_instance_json_coder.dump(schema_instance_class))
|
|
66
|
-
schema_instance_class.bar = 'whar'
|
|
67
|
-
assert_equal({'foo' => 'who', 'bar' => 'whar'}, schema_instance_json_coder.dump(schema_instance_class))
|
|
68
|
-
end
|
|
69
|
-
describe 'array' do
|
|
70
|
-
let(:options) { {array: true} }
|
|
71
|
-
it 'dumps an array of schema_instances' do
|
|
72
|
-
schema_instances = [schema.new_jsi(foo: 'x', bar: 'y'), schema.new_jsi(foo: 'z', bar: 'q')]
|
|
73
|
-
assert_equal([{"foo" => "x", "bar" => "y"}, {"foo" => "z", "bar" => "q"}], schema_instance_json_coder.dump(schema_instances))
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
describe 'array schema' do
|
|
77
|
-
let(:schema_content) { {items: {properties: {foo: {}, bar: {}}}} }
|
|
78
|
-
it 'dumps a schema_instance array' do
|
|
79
|
-
schema_instances = schema.new_jsi([{foo: 'x', bar: 'y'}, {foo: 'z', bar: 'q'}])
|
|
80
|
-
assert_equal([{"foo" => "x", "bar" => "y"}, {"foo" => "z", "bar" => "q"}], schema_instance_json_coder.dump(schema_instances))
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|