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