jsi 0.4.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +33 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +114 -42
  6. data/jsi.gemspec +14 -12
  7. data/lib/jsi/base/node.rb +183 -0
  8. data/lib/jsi/base.rb +388 -220
  9. data/lib/jsi/jsi_coder.rb +8 -7
  10. data/lib/jsi/metaschema.rb +0 -1
  11. data/lib/jsi/metaschema_node/bootstrap_schema.rb +101 -0
  12. data/lib/jsi/metaschema_node.rb +159 -135
  13. data/lib/jsi/ptr.rb +303 -0
  14. data/lib/jsi/schema/application/child_application/contains.rb +25 -0
  15. data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
  16. data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
  17. data/lib/jsi/schema/application/child_application/draft07.rb +29 -0
  18. data/lib/jsi/schema/application/child_application/items.rb +18 -0
  19. data/lib/jsi/schema/application/child_application/properties.rb +25 -0
  20. data/lib/jsi/schema/application/child_application.rb +38 -0
  21. data/lib/jsi/schema/application/draft04.rb +8 -0
  22. data/lib/jsi/schema/application/draft06.rb +8 -0
  23. data/lib/jsi/schema/application/draft07.rb +8 -0
  24. data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
  25. data/lib/jsi/schema/application/inplace_application/draft04.rb +26 -0
  26. data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
  27. data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -0
  28. data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
  29. data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
  30. data/lib/jsi/schema/application/inplace_application/someof.rb +44 -0
  31. data/lib/jsi/schema/application/inplace_application.rb +41 -0
  32. data/lib/jsi/schema/application.rb +12 -0
  33. data/lib/jsi/schema/draft04.rb +14 -0
  34. data/lib/jsi/schema/draft06.rb +14 -0
  35. data/lib/jsi/schema/draft07.rb +14 -0
  36. data/lib/jsi/schema/issue.rb +36 -0
  37. data/lib/jsi/schema/ref.rb +160 -0
  38. data/lib/jsi/schema/schema_ancestor_node.rb +113 -0
  39. data/lib/jsi/schema/validation/array.rb +69 -0
  40. data/lib/jsi/schema/validation/const.rb +20 -0
  41. data/lib/jsi/schema/validation/contains.rb +25 -0
  42. data/lib/jsi/schema/validation/core.rb +39 -0
  43. data/lib/jsi/schema/validation/dependencies.rb +49 -0
  44. data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
  45. data/lib/jsi/schema/validation/draft04.rb +112 -0
  46. data/lib/jsi/schema/validation/draft06.rb +122 -0
  47. data/lib/jsi/schema/validation/draft07.rb +159 -0
  48. data/lib/jsi/schema/validation/enum.rb +25 -0
  49. data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
  50. data/lib/jsi/schema/validation/items.rb +54 -0
  51. data/lib/jsi/schema/validation/not.rb +20 -0
  52. data/lib/jsi/schema/validation/numeric.rb +121 -0
  53. data/lib/jsi/schema/validation/object.rb +45 -0
  54. data/lib/jsi/schema/validation/pattern.rb +34 -0
  55. data/lib/jsi/schema/validation/properties.rb +101 -0
  56. data/lib/jsi/schema/validation/property_names.rb +32 -0
  57. data/lib/jsi/schema/validation/ref.rb +40 -0
  58. data/lib/jsi/schema/validation/required.rb +27 -0
  59. data/lib/jsi/schema/validation/someof.rb +90 -0
  60. data/lib/jsi/schema/validation/string.rb +47 -0
  61. data/lib/jsi/schema/validation/type.rb +49 -0
  62. data/lib/jsi/schema/validation.rb +51 -0
  63. data/lib/jsi/schema.rb +508 -149
  64. data/lib/jsi/schema_classes.rb +199 -59
  65. data/lib/jsi/schema_registry.rb +151 -0
  66. data/lib/jsi/schema_set.rb +181 -0
  67. data/lib/jsi/simple_wrap.rb +23 -4
  68. data/lib/jsi/util/private/attr_struct.rb +127 -0
  69. data/lib/jsi/util/private.rb +204 -0
  70. data/lib/jsi/util/typelike.rb +229 -0
  71. data/lib/jsi/util.rb +89 -53
  72. data/lib/jsi/validation/error.rb +34 -0
  73. data/lib/jsi/validation/result.rb +210 -0
  74. data/lib/jsi/validation.rb +15 -0
  75. data/lib/jsi/version.rb +3 -1
  76. data/lib/jsi.rb +44 -14
  77. data/lib/schemas/json-schema.org/draft-04/schema.rb +10 -3
  78. data/lib/schemas/json-schema.org/draft-06/schema.rb +10 -3
  79. data/lib/schemas/json-schema.org/draft-07/schema.rb +14 -0
  80. data/readme.rb +138 -0
  81. data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
  82. data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
  83. data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
  84. metadata +75 -122
  85. data/.simplecov +0 -3
  86. data/Rakefile.rb +0 -9
  87. data/lib/jsi/base/to_rb.rb +0 -128
  88. data/lib/jsi/json/node.rb +0 -203
  89. data/lib/jsi/json/pointer.rb +0 -419
  90. data/lib/jsi/json-schema-fragments.rb +0 -61
  91. data/lib/jsi/json.rb +0 -10
  92. data/lib/jsi/pathed_node.rb +0 -118
  93. data/lib/jsi/typelike_modules.rb +0 -240
  94. data/resources/icons/AGPL-3.0.png +0 -0
  95. data/test/base_array_test.rb +0 -323
  96. data/test/base_hash_test.rb +0 -337
  97. data/test/base_test.rb +0 -486
  98. data/test/jsi_coder_test.rb +0 -85
  99. data/test/jsi_json_arraynode_test.rb +0 -150
  100. data/test/jsi_json_hashnode_test.rb +0 -132
  101. data/test/jsi_json_node_test.rb +0 -257
  102. data/test/jsi_json_pointer_test.rb +0 -102
  103. data/test/jsi_test.rb +0 -11
  104. data/test/jsi_typelike_as_json_test.rb +0 -53
  105. data/test/metaschema_node_test.rb +0 -19
  106. data/test/schema_module_test.rb +0 -21
  107. data/test/schema_test.rb +0 -208
  108. data/test/spreedly_openapi_test.rb +0 -8
  109. data/test/test_helper.rb +0 -97
  110. 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
@@ -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