jsi 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +36 -0
  4. data/LICENSE.md +613 -0
  5. data/README.md +153 -52
  6. data/lib/jsi/base.rb +485 -338
  7. data/lib/jsi/jsi_coder.rb +24 -18
  8. data/lib/jsi/metaschema.rb +7 -0
  9. data/lib/jsi/metaschema_node/bootstrap_schema.rb +100 -0
  10. data/lib/jsi/metaschema_node.rb +245 -0
  11. data/lib/jsi/pathed_node.rb +49 -46
  12. data/lib/jsi/ptr.rb +292 -0
  13. data/lib/jsi/schema/application/child_application/contains.rb +16 -0
  14. data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
  15. data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
  16. data/lib/jsi/schema/application/child_application/draft07.rb +29 -0
  17. data/lib/jsi/schema/application/child_application/items.rb +18 -0
  18. data/lib/jsi/schema/application/child_application/properties.rb +25 -0
  19. data/lib/jsi/schema/application/child_application.rb +40 -0
  20. data/lib/jsi/schema/application/draft04.rb +8 -0
  21. data/lib/jsi/schema/application/draft06.rb +8 -0
  22. data/lib/jsi/schema/application/draft07.rb +8 -0
  23. data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
  24. data/lib/jsi/schema/application/inplace_application/draft04.rb +26 -0
  25. data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
  26. data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -0
  27. data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
  28. data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
  29. data/lib/jsi/schema/application/inplace_application/someof.rb +29 -0
  30. data/lib/jsi/schema/application/inplace_application.rb +46 -0
  31. data/lib/jsi/schema/application.rb +12 -0
  32. data/lib/jsi/schema/draft04.rb +14 -0
  33. data/lib/jsi/schema/draft06.rb +14 -0
  34. data/lib/jsi/schema/draft07.rb +14 -0
  35. data/lib/jsi/schema/issue.rb +36 -0
  36. data/lib/jsi/schema/ref.rb +159 -0
  37. data/lib/jsi/schema/schema_ancestor_node.rb +119 -0
  38. data/lib/jsi/schema/validation/array.rb +69 -0
  39. data/lib/jsi/schema/validation/const.rb +20 -0
  40. data/lib/jsi/schema/validation/contains.rb +25 -0
  41. data/lib/jsi/schema/validation/core.rb +39 -0
  42. data/lib/jsi/schema/validation/dependencies.rb +49 -0
  43. data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
  44. data/lib/jsi/schema/validation/draft04.rb +112 -0
  45. data/lib/jsi/schema/validation/draft06.rb +122 -0
  46. data/lib/jsi/schema/validation/draft07.rb +159 -0
  47. data/lib/jsi/schema/validation/enum.rb +25 -0
  48. data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
  49. data/lib/jsi/schema/validation/items.rb +54 -0
  50. data/lib/jsi/schema/validation/not.rb +20 -0
  51. data/lib/jsi/schema/validation/numeric.rb +121 -0
  52. data/lib/jsi/schema/validation/object.rb +45 -0
  53. data/lib/jsi/schema/validation/pattern.rb +34 -0
  54. data/lib/jsi/schema/validation/properties.rb +101 -0
  55. data/lib/jsi/schema/validation/property_names.rb +32 -0
  56. data/lib/jsi/schema/validation/ref.rb +40 -0
  57. data/lib/jsi/schema/validation/required.rb +27 -0
  58. data/lib/jsi/schema/validation/someof.rb +90 -0
  59. data/lib/jsi/schema/validation/string.rb +47 -0
  60. data/lib/jsi/schema/validation/type.rb +49 -0
  61. data/lib/jsi/schema/validation.rb +51 -0
  62. data/lib/jsi/schema.rb +528 -233
  63. data/lib/jsi/schema_classes.rb +238 -51
  64. data/lib/jsi/schema_registry.rb +141 -0
  65. data/lib/jsi/schema_set.rb +141 -0
  66. data/lib/jsi/simple_wrap.rb +8 -3
  67. data/lib/jsi/typelike_modules.rb +75 -68
  68. data/lib/jsi/util/attr_struct.rb +106 -0
  69. data/lib/jsi/util.rb +167 -64
  70. data/lib/jsi/validation/error.rb +34 -0
  71. data/lib/jsi/validation/result.rb +210 -0
  72. data/lib/jsi/validation.rb +15 -0
  73. data/lib/jsi/version.rb +3 -1
  74. data/lib/jsi.rb +72 -9
  75. data/lib/schemas/json-schema.org/draft-04/schema.rb +12 -0
  76. data/lib/schemas/json-schema.org/draft-06/schema.rb +12 -0
  77. data/lib/schemas/json-schema.org/draft-07/schema.rb +12 -0
  78. data/readme.rb +138 -0
  79. data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
  80. data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
  81. data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
  82. metadata +80 -107
  83. data/.simplecov +0 -1
  84. data/LICENSE.txt +0 -21
  85. data/Rakefile.rb +0 -9
  86. data/jsi.gemspec +0 -31
  87. data/lib/jsi/base/to_rb.rb +0 -126
  88. data/lib/jsi/json/node.rb +0 -243
  89. data/lib/jsi/json/pointer.rb +0 -330
  90. data/lib/jsi/json-schema-fragments.rb +0 -59
  91. data/lib/jsi/json.rb +0 -8
  92. data/test/base_array_test.rb +0 -209
  93. data/test/base_hash_test.rb +0 -204
  94. data/test/base_test.rb +0 -422
  95. data/test/jsi_coder_test.rb +0 -85
  96. data/test/jsi_json_arraynode_test.rb +0 -150
  97. data/test/jsi_json_hashnode_test.rb +0 -132
  98. data/test/jsi_json_node_test.rb +0 -310
  99. data/test/jsi_json_pointer_test.rb +0 -106
  100. data/test/jsi_test.rb +0 -11
  101. data/test/jsi_typelike_as_json_test.rb +0 -53
  102. data/test/schema_test.rb +0 -196
  103. data/test/spreedly_openapi_test.rb +0 -8
  104. data/test/test_helper.rb +0 -63
  105. data/test/util_test.rb +0 -62
@@ -1,310 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe JSI::JSON::Node do
4
- let(:path) { [] }
5
- let(:pointer) { JSI::JSON::Pointer.new(path) }
6
- let(:node) { JSI::JSON::Node.new(document, pointer) }
7
-
8
- describe 'initialization' do
9
- it 'initializes' do
10
- node = JSI::JSON::Node.new({'a' => 'b'}, pointer)
11
- assert_equal({'a' => 'b'}, node.document)
12
- assert_equal(JSI::JSON::Pointer.new([]), node.pointer)
13
- end
14
- it 'initializes, pointer is not pointer' do
15
- err = assert_raises(TypeError) { JSI::JSON::Node.new({'a' => 'b'}, []) }
16
- assert_equal('pointer must be a JSI::JSON::Pointer. got: [] (Array)', err.message)
17
- end
18
- it 'initializes, document is another Node' do
19
- err = assert_raises(TypeError) { JSI::JSON::Node.new(JSI::JSON::Node.new({'a' => 'b'}, pointer), pointer) }
20
- assert_equal("document of a Node should not be another JSI::JSON::Node: #<JSI::JSON::Node fragment=\"#\" {\"a\"=>\"b\"}>", err.message)
21
- end
22
- end
23
- describe 'initialization by .new_by_type' do
24
- it 'initializes HashNode' do
25
- node = JSI::JSON::Node.new_doc({'a' => 'b'})
26
- assert_instance_of(JSI::JSON::HashNode, node)
27
- assert_equal({'a' => 'b'}, node.document)
28
- end
29
- it 'initializes ArrayNode' do
30
- node = JSI::JSON::Node.new_doc(['a', 'b'])
31
- assert_instance_of(JSI::JSON::ArrayNode, node)
32
- assert_equal(['a', 'b'], node.document)
33
- end
34
- it 'initializes Node' do
35
- object = Object.new
36
- node = JSI::JSON::Node.new_doc(object)
37
- assert_instance_of(JSI::JSON::Node, node)
38
- assert_equal(object, node.document)
39
- end
40
- end
41
- describe '#pointer' do
42
- it 'is a JSI::JSON::Pointer' do
43
- assert_instance_of(JSI::JSON::Pointer, JSI::JSON::Node.new({}, pointer).pointer)
44
- end
45
- end
46
- describe '#path' do
47
- it 'is an array of reference tokens' do
48
- assert_equal(['a'], JSI::JSON::Node.new({}, JSI::JSON::Pointer.new(['a'])).path)
49
- end
50
- end
51
- describe '#content' do
52
- it 'returns the content at the root' do
53
- assert_equal({'a' => 'b'}, JSI::JSON::Node.new({'a' => 'b'}, pointer).content)
54
- end
55
- it 'returns the content from the deep' do
56
- assert_equal('b', JSI::JSON::Node.new([0, {'x' => [{'a' => ['b']}]}], JSI::JSON::Pointer.new([1, 'x', 0, 'a', 0])).content)
57
- end
58
- end
59
- describe '#deref' do
60
- let(:document) do
61
- {
62
- 'foo' => {'bar' => ['baz']},
63
- 'a' => {'$ref' => '#/foo'},
64
- }
65
- end
66
- it 'follows a $ref' do
67
- assert_equal({'bar' => ['baz']}, node['a'].deref.content)
68
- end
69
- it 'returns the node when there is no $ref to follow' do
70
- assert_equal({'bar' => ['baz']}, node['foo'].deref.content)
71
- end
72
- describe "dealing with google's invalid $refs" do
73
- let(:document) do
74
- {
75
- 'schemas' => {'bar' => {'description' => ['baz']}},
76
- 'a' => {'$ref' => 'bar', 'foo' => 'bar'},
77
- }
78
- end
79
- it 'subscripts a node consisting of a $ref WITHOUT following' do
80
- subscripted = node['a']
81
- assert_equal({'$ref' => 'bar', 'foo' => 'bar'}, subscripted.content)
82
- assert_equal(JSI::JSON::Pointer.new(['a']), subscripted.pointer)
83
- end
84
- it 'looks for a node in #/schemas with the name of the $ref' do
85
- assert_equal({'description' => ['baz']}, node['a'].deref.content)
86
- end
87
- it 'follows a $ref when subscripting past it' do
88
- subscripted = node['a']['description']
89
- assert_equal(['baz'], subscripted.content)
90
- assert_equal(JSI::JSON::Pointer.new(['schemas', 'bar', 'description']), subscripted.pointer)
91
- end
92
- it 'does not follow a $ref when subscripting a key that is present' do
93
- subscripted = node['a']['foo']
94
- assert_equal('bar', subscripted)
95
- end
96
- end
97
- describe "dealing with whatever this is" do
98
- # I think google uses this style in some cases maybe. I don't remember.
99
- let(:document) do
100
- {
101
- 'schemas' => {'bar' => {'id' => 'BarID', 'description' => 'baz'}},
102
- 'a' => {'$ref' => 'BarID'},
103
- }
104
- end
105
- it 'looks for a node in #/schemas with the name of the $ref' do
106
- assert_equal({'id' => 'BarID', 'description' => 'baz'}, node['a'].deref.content)
107
- end
108
- end
109
- end
110
- describe '#[]' do
111
- describe 'without dereferencing' do
112
- let(:document) { [0, {'x' => [{'a' => ['b']}]}] }
113
- it 'subscripts arrays and hashes' do
114
- assert_equal('b', node[1]['x'][0]['a'][0])
115
- end
116
- it 'returns ArrayNode for an array' do
117
- subscripted = node[1]['x']
118
- assert_instance_of(JSI::JSON::ArrayNode, subscripted)
119
- assert_equal([{'a' => ['b']}], subscripted.content)
120
- assert_equal(JSI::JSON::Pointer.new([1, 'x']), subscripted.pointer)
121
- end
122
- it 'returns HashNode for a Hash' do
123
- subscripted = node[1]
124
- assert_instance_of(JSI::JSON::HashNode, subscripted)
125
- assert_equal({'x' => [{'a' => ['b']}]}, subscripted.content)
126
- assert_equal(JSI::JSON::Pointer.new([1]), subscripted.pointer)
127
- end
128
- describe 'content does not respond to []' do
129
- let(:document) { Object.new }
130
- it 'cannot subscript' do
131
- err = assert_raises(NoMethodError) { node['x'] }
132
- assert_equal("undefined method `[]`\nsubscripting with \"x\" (String) from Object. content is: #{document.pretty_inspect.chomp}", err.message)
133
- end
134
- end
135
- end
136
- describe 'with dereferencing' do
137
- let(:document) do
138
- {
139
- 'foo' => {'bar' => ['baz']},
140
- 'a' => {'$ref' => '#/foo', 'description' => 'hi'}, # not sure a description is actually allowed here, whatever
141
- }
142
- end
143
- it 'subscripts a node consisting of a $ref WITHOUT following' do
144
- subscripted = node['a']
145
- assert_equal({'$ref' => '#/foo', 'description' => 'hi'}, subscripted.content)
146
- assert_equal(JSI::JSON::Pointer.new(['a']), subscripted.pointer)
147
- end
148
- it 'follows a $ref when subscripting past it' do
149
- subscripted = node['a']['bar']
150
- assert_equal(['baz'], subscripted.content)
151
- assert_equal(JSI::JSON::Pointer.new(['foo', 'bar']), subscripted.pointer)
152
- end
153
- it 'does not follow a $ref when subscripting a key that is present' do
154
- subscripted = node['a']['description']
155
- assert_equal('hi', subscripted)
156
- end
157
- end
158
- end
159
- describe '#[]=' do
160
- let(:document) { [0, {'x' => [{'a' => ['b']}]}] }
161
- it 'assigns' do
162
- node[0] = 'abcdefg'
163
- assert_equal(['abcdefg', {'x' => [{'a' => ['b']}]}], document)
164
- string_node = JSI::JSON::Node.new(document, JSI::JSON::Pointer.new([0]))
165
- string_node[0..2] = '0'
166
- assert_equal(['0defg', {'x' => [{'a' => ['b']}]}], document)
167
- node[0] = node[1]
168
- assert_equal([{'x' => [{'a' => ['b']}]}, {'x' => [{'a' => ['b']}]}], document)
169
- end
170
- it 'assigns, deeper' do
171
- node[1]['y'] = node[1]['x'][0]
172
- assert_equal([0, {'x' => [{'a' => ['b']}], 'y' => {'a' => ['b']}}], document)
173
- end
174
- end
175
- describe '#document_node' do
176
- let(:document) { {'a' => {'b' => 3}} }
177
- it 'has content that is the document' do
178
- assert_equal({'a' => {'b' => 3}}, node['a'].document_node.content)
179
- end
180
- end
181
- describe '#parent_node' do
182
- let(:document) { {'a' => {'b' => []}} }
183
- it 'finds a parent' do
184
- sub = node['a']['b']
185
- assert_equal(JSI::JSON::Pointer.new(['a', 'b']), sub.pointer)
186
- parent = sub.parent_node
187
- assert_equal(JSI::JSON::Pointer.new(['a']), parent.pointer)
188
- assert_equal({'b' => []}, parent.content)
189
- assert_equal(node['a'], parent)
190
- root_from_sub = sub.parent_node.parent_node
191
- assert_equal(JSI::JSON::Pointer.new([]), root_from_sub.pointer)
192
- assert_equal({'a' => {'b' => []}}, root_from_sub.content)
193
- assert_equal(node, root_from_sub)
194
- err = assert_raises(JSI::JSON::Pointer::ReferenceError) do
195
- root_from_sub.parent_node
196
- end
197
- assert_match(/\Acannot access parent of root pointer: #<JSI::JSON::Pointer/, err.message)
198
- end
199
- end
200
- describe '#pointer_path' do
201
- let(:document) { {'a' => {'b' => 3}} }
202
- it 'is empty' do
203
- assert_equal('', node.pointer_path)
204
- end
205
- it 'is not empty' do
206
- assert_equal('/a', node['a'].pointer_path)
207
- end
208
- describe 'containing an empty string and some slashes and tildes that need escaping' do
209
- let(:document) { {'' => {'a/b~c!d#e[f]' => []}} }
210
- it 'matches' do
211
- assert_equal('//a~1b~0c!d#e[f]', node['']['a/b~c!d#e[f]'].pointer_path)
212
- end
213
- end
214
- end
215
- describe '#fragment' do
216
- let(:document) { {'a' => {'b' => 3}} }
217
- it 'is empty' do
218
- assert_equal('#', node.fragment)
219
- end
220
- it 'is not empty' do
221
- assert_equal('#/a', node['a'].fragment)
222
- end
223
- describe 'containing an empty string and some slashes and tildes that need escaping' do
224
- let(:document) { {'' => {'a/b~c!d#e[f]' => []}} }
225
- it 'matches' do
226
- assert_equal('#//a~1b~0c!d#e%5Bf%5D', node['']['a/b~c!d#e[f]'].fragment)
227
- end
228
- end
229
- end
230
- describe '#modified_copy' do
231
- let(:document) { [['b', 'q'], {'c' => ['d', 'e']}] }
232
- let(:path) { ['1', 'c'] }
233
- it 'returns a different object' do
234
- # simplest thing
235
- modified_dup = node.modified_copy(&:dup)
236
- # it is equal - being a dup
237
- assert_equal(modified_dup, node)
238
- # but different object
239
- refute_equal(node.object_id, modified_dup.object_id)
240
- # the parents, obviously, are different
241
- refute_equal(node.parent_node.content.object_id, modified_dup.parent_node.content.object_id)
242
- refute_equal(node.parent_node.parent_node.content.object_id, modified_dup.parent_node.parent_node.content.object_id)
243
- # but any untouched part(s) - in this case the ['b', 'q'] at document[0] - are untouched
244
- assert_equal(node.document_node[0].content.object_id, modified_dup.document_node[0].content.object_id)
245
- end
246
- it 'returns the same object' do
247
- unmodified_dup = node.modified_copy { |o| o }
248
- assert_equal(unmodified_dup, node)
249
- # same object, since the block just returned it
250
- refute_equal(node.object_id, unmodified_dup.object_id)
251
- # the parents are unchanged since the object is the same
252
- assert_equal(node.parent_node.content.object_id, unmodified_dup.parent_node.content.object_id)
253
- assert_equal(node.parent_node.parent_node.content.object_id, unmodified_dup.parent_node.parent_node.content.object_id)
254
- # same as the other: any untouched part(s) - in this case the ['b', 'q'] at document[0] - are untouched
255
- assert_equal(node.document_node[0].content.object_id, unmodified_dup.document_node[0].content.object_id)
256
- end
257
- it 'raises subscripting string from array' do
258
- err = assert_raises(TypeError) { JSI::JSON::Node.new(document, JSI::JSON::Pointer.new(['x'])).modified_copy(&:dup) }
259
- assert_match(%r(\Abad subscript "x" with remaining subpath: \[\] for array: \[.*\]\z)m, err.message)
260
- end
261
- it 'raises subscripting from invalid subpath' do
262
- err = assert_raises(TypeError) { JSI::JSON::Node.new(document, JSI::JSON::Pointer.new([0, 0, 'what'])).modified_copy(&:dup) }
263
- assert_match(%r(bad subscript: "what" with remaining subpath: \[\] for content: "b"\z)m, err.message)
264
- end
265
- end
266
- describe '#inspect' do
267
- let(:document) { {'a' => {'c' => ['d', 'e']}} }
268
- let(:path) { ['a'] }
269
- it 'inspects' do
270
- assert_equal(%Q(#<JSI::JSON::Node fragment="#/a" {"c"=>["d", "e"]}>), node.inspect)
271
- end
272
- end
273
- describe '#pretty_print' do
274
- let(:document) { {'a' => {'c' => ['d', 'e']}} }
275
- let(:path) { ['a'] }
276
- it 'pretty prints' do
277
- assert_equal(%Q(#<JSI::JSON::Node fragment="#/a" {"c"=>["d", "e"]}>), node.pretty_inspect.chomp)
278
- end
279
- end
280
- describe '#fingerprint' do
281
- let(:pointer) { JSI::JSON::Pointer.new([]) }
282
- it 'hashes consistently' do
283
- assert_equal('x', {JSI::JSON::Node.new([0], pointer) => 'x'}[JSI::JSON::Node.new([0], pointer)])
284
- end
285
- it 'hashes consistently regardless of the Node being decorated as a subclass' do
286
- assert_equal('x', {JSI::JSON::Node.new_doc([0]) => 'x'}[JSI::JSON::Node.new([0], pointer)])
287
- assert_equal('x', {JSI::JSON::Node.new([0], pointer) => 'x'}[JSI::JSON::Node.new_doc([0])])
288
- end
289
- it '==' do
290
- assert_equal(JSI::JSON::Node.new([0], pointer), JSI::JSON::Node.new([0], pointer))
291
- assert_equal(JSI::JSON::Node.new_doc([0]), JSI::JSON::Node.new([0], pointer))
292
- assert_equal(JSI::JSON::Node.new([0], pointer), JSI::JSON::Node.new_doc([0]))
293
- assert_equal(JSI::JSON::Node.new_doc([0]), JSI::JSON::Node.new_doc([0]))
294
- end
295
- it '!=' do
296
- refute_equal(JSI::JSON::Node.new([0], pointer), JSI::JSON::Node.new({}, pointer))
297
- refute_equal(JSI::JSON::Node.new_doc([0]), JSI::JSON::Node.new({}, pointer))
298
- refute_equal(JSI::JSON::Node.new([0], pointer), JSI::JSON::Node.new_doc({}))
299
- refute_equal(JSI::JSON::Node.new_doc([0]), JSI::JSON::Node.new_doc({}))
300
- refute_equal({}, JSI::JSON::Node.new_doc({}))
301
- refute_equal(JSI::JSON::Node.new_doc({}), {})
302
- end
303
- end
304
- describe '#as_json' do
305
- let(:document) { {'a' => 'b'} }
306
- it '#as_json' do
307
- assert_equal({'a' => 'b'}, node.as_json)
308
- end
309
- end
310
- end
@@ -1,106 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe JSI::JSON::Pointer do
4
- # For example, given the document
5
- let(:document) do
6
- {
7
- "foo" => ["bar", "baz"],
8
- "" => 0,
9
- "a/b" => 1,
10
- "c%d" => 2,
11
- "e^f" => 3,
12
- "g|h" => 4,
13
- "i\\j" => 5,
14
- "k\"l" => 6,
15
- " " => 7,
16
- "m~n" => 8,
17
- }
18
- end
19
-
20
- describe 'initialize from pointer' do
21
- it 'parses' do
22
- # The following strings evaluate to the accompanying values:
23
- evaluations = [
24
- "" , document,
25
- "/foo" , ["bar", "baz"],
26
- "/foo/0", "bar",
27
- "/" , 0,
28
- "/a~1b" , 1,
29
- "/c%d" , 2,
30
- "/e^f" , 3,
31
- "/g|h" , 4,
32
- "/i\\j" , 5,
33
- "/k\"l" , 6,
34
- "/ " , 7,
35
- "/m~0n" , 8,
36
- ]
37
- evaluations.each_slice(2) do |pointer, value|
38
- assert_equal(value, JSI::JSON::Pointer.from_pointer(pointer).evaluate(document))
39
- end
40
- end
41
-
42
- it 'raises for invalid syntax' do
43
- err = assert_raises(JSI::JSON::Pointer::PointerSyntaxError) do
44
- JSI::JSON::Pointer.from_pointer("this does not begin with slash").evaluate(document)
45
- end
46
- assert_equal("Invalid pointer syntax in \"this does not begin with slash\": pointer must begin with /", err.message)
47
- end
48
- end
49
- describe 'initialize from fragment' do
50
- # For example, given the document
51
- let(:document) do
52
- {
53
- "foo" => ["bar", "baz"],
54
- "" => 0,
55
- "a/b" => 1,
56
- "c%d" => 2,
57
- "e^f" => 3,
58
- "g|h" => 4,
59
- "i\\j" => 5,
60
- "k\"l" => 6,
61
- " " => 7,
62
- "m~n" => 8,
63
- }
64
- end
65
-
66
- it 'parses' do
67
- # the following URI fragment identifiers evaluate to the accompanying values:
68
- evaluations = [
69
- '#', document,
70
- '#/foo', ["bar", "baz"],
71
- '#/foo/0', "bar",
72
- '#/', 0,
73
- '#/a~1b', 1,
74
- '#/c%25d', 2,
75
- '#/e%5Ef', 3,
76
- '#/g%7Ch', 4,
77
- '#/i%5Cj', 5,
78
- '#/k%22l', 6,
79
- '#/%20', 7,
80
- '#/m~0n', 8,
81
- ]
82
- evaluations.each_slice(2) do |fragment, value|
83
- assert_equal(value, JSI::JSON::Pointer.from_fragment(fragment).evaluate(document))
84
- end
85
- end
86
-
87
- it 'raises for invalid syntax' do
88
- err = assert_raises(JSI::JSON::Pointer::PointerSyntaxError) do
89
- JSI::JSON::Pointer.from_fragment("this does not begin with #").evaluate(document)
90
- end
91
- assert_equal("Invalid fragment syntax in \"this does not begin with #\": fragment must begin with #", err.message)
92
- err = assert_raises(JSI::JSON::Pointer::PointerSyntaxError) do
93
- JSI::JSON::Pointer.from_fragment("#this does not begin with slash").evaluate(document)
94
- end
95
- assert_equal("Invalid pointer syntax in \"this does not begin with slash\": pointer must begin with /", err.message)
96
- end
97
- end
98
- describe 'initialize' do
99
- describe 'invalid reference_tokens' do
100
- it 'raises' do
101
- err = assert_raises(TypeError) { JSI::JSON::Pointer.new({}) }
102
- assert_equal("reference_tokens must be an array. got: {}", err.message)
103
- end
104
- end
105
- end
106
- end
data/test/jsi_test.rb DELETED
@@ -1,11 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- class JSITest < Minitest::Test
4
- def test_that_it_has_a_version_number
5
- refute_nil ::JSI::VERSION
6
- end
7
-
8
- def test_it_does_something_useful
9
- assert true
10
- end
11
- end
@@ -1,53 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- class JSONifiable
4
- def initialize(object)
5
- @object = object
6
- end
7
- def as_json
8
- @object
9
- end
10
- end
11
-
12
- describe JSI::Typelike do
13
- describe 'as_json' do
14
- it 'expresses as json' do
15
- assert_equal({}, JSI::Typelike.as_json({}))
16
- assert_equal([], JSI::Typelike.as_json([]))
17
-
18
- # symbols to string
19
- assert_equal(['a'], JSI::Typelike.as_json([:a]))
20
-
21
- # set
22
- assert_equal(['a'], JSI::Typelike.as_json(Set.new(['a'])))
23
-
24
- # responds to #to_hash / #to_ary but naught else
25
- assert_equal({'a' => 'b'}, JSI::Typelike.as_json(SortOfHash.new({'a' => 'b'})))
26
- assert_equal(['a'], JSI::Typelike.as_json(SortOfArray.new(['a'])))
27
-
28
- # symbol keys to string
29
- assert_equal({'a' => 'b'}, JSI::Typelike.as_json({a: 'b'}))
30
- # non string/symbol key
31
- err = assert_raises(TypeError) { JSI::Typelike.as_json({nil => 0}) }
32
- assert_equal('json object (hash) cannot be keyed with: nil', err.message)
33
-
34
- # schema
35
- schema = JSI::Schema.from_object({'type' => 'array'})
36
- assert_equal({'type' => 'array'}, JSI::Typelike.as_json(schema))
37
-
38
- # JSI
39
- assert_equal(['a'], JSI::Typelike.as_json(JSI.class_for_schema(schema).new(['a'])))
40
-
41
- # JSON::Node
42
- assert_equal(['a'], JSI::Typelike.as_json(JSI::JSON::Node.new_doc(['a'])))
43
-
44
- # #as_json
45
- assert_equal(['a'], JSI::Typelike.as_json(JSONifiable.new(['a'])))
46
-
47
- # not jsonifiable
48
- object = Object.new
49
- err = assert_raises(TypeError) { JSI::Typelike.as_json(object) }
50
- assert_equal("cannot express object as json: #{object.pretty_inspect.chomp}", err.message)
51
- end
52
- end
53
- end
data/test/schema_test.rb DELETED
@@ -1,196 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- SomeMetaschema = JSI.class_for_schema({id: 'https://schemas.jsi.unth.net/test/somemetaschema', type: 'object'})
4
-
5
- describe JSI::Schema do
6
- describe 'new' do
7
- it 'initializes from a hash' do
8
- schema = JSI::Schema.new({'type' => 'object'})
9
- assert_equal(JSI::JSON::Node.new_doc({'type' => 'object'}), schema.schema_node)
10
- end
11
- it 'initializes from a Node' do
12
- schema_node = JSI::JSON::Node.new_doc({'type' => 'object'})
13
- schema = JSI::Schema.new(schema_node)
14
- assert_equal(schema_node, schema.schema_node)
15
- assert_equal(schema_node, schema.schema_object)
16
- end
17
- it 'initializes from a JSI' do
18
- schema_jsi = SomeMetaschema.new('type' => 'object')
19
- schema = JSI::Schema.new(schema_jsi)
20
- assert_equal(schema_jsi, schema.schema_node)
21
- assert_equal(schema_jsi, schema.schema_object)
22
- end
23
- it 'cannot instantiate from some unknown object' do
24
- err = assert_raises(TypeError) { JSI::Schema.new(Object.new) }
25
- assert_match(/\Acannot instantiate Schema from: #<Object:.*>\z/m, err.message)
26
- end
27
- it 'makes no sense to instantiate schema from schema' do
28
- err = assert_raises(TypeError) { JSI::Schema.new(JSI::Schema.new({})) }
29
- assert_match(/\Awill not instantiate Schema from another Schema: #<JSI::Schema schema_id=.*>\z/m, err.message)
30
- end
31
- end
32
- describe 'as an instance of metaschema' do
33
- let(:default_metaschema) do
34
- validator = ::JSON::Validator.default_validator
35
- metaschema_file = validator.metaschema
36
- JSI::Schema.new(::JSON.parse(File.read(metaschema_file)))
37
- end
38
- let(:metaschema_jsi_class) { JSI.class_for_schema(default_metaschema) }
39
- let(:schema_object) { {'type' => 'array', 'items' => {'description' => 'items!'}} }
40
- let(:schema_jsi) { metaschema_jsi_class.new(schema_object) }
41
- let(:schema) { JSI::Schema.new(schema_jsi) }
42
- it '#[]' do
43
- schema_items = schema['items']
44
- assert_instance_of(metaschema_jsi_class, schema_items)
45
- assert_equal({'description' => 'items!'}, schema_items.as_json)
46
- end
47
- end
48
- describe '#schema_id' do
49
- it 'generates one' do
50
- assert_match(/\A[0-9a-f\-]+#\z/, JSI::Schema.new({}).schema_id)
51
- end
52
- it 'uses a given id with a fragment' do
53
- schema = JSI::Schema.new({id: 'https://schemas.jsi.unth.net/test/given_id#'})
54
- assert_equal('https://schemas.jsi.unth.net/test/given_id#', schema.schema_id)
55
- end
56
- it 'uses a given id (adding a fragment)' do
57
- schema = JSI::Schema.new({id: 'https://schemas.jsi.unth.net/test/given_id'})
58
- assert_equal('https://schemas.jsi.unth.net/test/given_id#', schema.schema_id)
59
- end
60
- it 'uses a pointer in the fragment' do
61
- schema_node = JSI::JSON::Node.new_doc({
62
- 'id' => 'https://schemas.jsi.unth.net/test/given_id#',
63
- 'properties' => {'foo' => {'type' => 'object'}},
64
- })
65
- schema = JSI::Schema.new(schema_node['properties']['foo'])
66
- assert_equal('https://schemas.jsi.unth.net/test/given_id#/properties/foo', schema.schema_id)
67
- end
68
- it 'uses a pointer in the fragment relative to the fragment of the root' do
69
- schema_node = JSI::JSON::Node.new_doc({
70
- 'id' => 'https://schemas.jsi.unth.net/test/given_id#/notroot',
71
- 'properties' => {'foo' => {'type' => 'object'}},
72
- })
73
- schema = JSI::Schema.new(schema_node['properties']['foo'])
74
- assert_equal('https://schemas.jsi.unth.net/test/given_id#/notroot/properties/foo', schema.schema_id)
75
- end
76
- end
77
- describe '#schema_class' do
78
- it 'returns the class for the schema' do
79
- schema_node = JSI::JSON::Node.new_doc({'id' => 'https://schemas.jsi.unth.net/test/schema_schema_class'})
80
- assert_equal(JSI.class_for_schema(schema_node), JSI::Schema.new(schema_node).schema_class)
81
- end
82
- end
83
- describe '#subschema_for_property' do
84
- let(:schema) do
85
- JSI::Schema.new({
86
- properties: {foo: {description: 'foo'}},
87
- patternProperties: {"^ba" => {description: 'ba*'}},
88
- additionalProperties: {description: 'whatever'},
89
- })
90
- end
91
- it 'has no subschema' do
92
- assert_equal(nil, JSI::Schema.new({}).subschema_for_property('no'))
93
- end
94
- it 'has a subschema by property' do
95
- subschema = schema.subschema_for_property('foo')
96
- assert_instance_of(JSI::Schema, subschema)
97
- assert_equal('foo', subschema['description'])
98
- end
99
- it 'has a subschema by pattern property' do
100
- subschema = schema.subschema_for_property('bar')
101
- assert_instance_of(JSI::Schema, subschema)
102
- assert_equal('ba*', subschema['description'])
103
- end
104
- it 'has a subschema by additional properties' do
105
- subschema = schema.subschema_for_property('anything')
106
- assert_instance_of(JSI::Schema, subschema)
107
- assert_equal('whatever', subschema['description'])
108
- end
109
- end
110
- describe '#subschema_for_index' do
111
- it 'has no subschema' do
112
- assert_equal(nil, JSI::Schema.new({}).subschema_for_index(0))
113
- end
114
- it 'has a subschema for items' do
115
- schema = JSI::Schema.new({
116
- items: {description: 'items!'}
117
- })
118
- first_subschema = schema.subschema_for_index(0)
119
- assert_instance_of(JSI::Schema, first_subschema)
120
- assert_equal('items!', first_subschema['description'])
121
- last_subschema = schema.subschema_for_index(1)
122
- assert_instance_of(JSI::Schema, last_subschema)
123
- assert_equal('items!', last_subschema['description'])
124
- end
125
- it 'has a subschema for each item by index' do
126
- schema = JSI::Schema.new({
127
- items: [{description: 'item one'}, {description: 'item two'}]
128
- })
129
- first_subschema = schema.subschema_for_index(0)
130
- assert_instance_of(JSI::Schema, first_subschema)
131
- assert_equal('item one', first_subschema['description'])
132
- last_subschema = schema.subschema_for_index(1)
133
- assert_instance_of(JSI::Schema, last_subschema)
134
- assert_equal('item two', last_subschema['description'])
135
- end
136
- it 'has a subschema by additional items' do
137
- schema = JSI::Schema.new({
138
- items: [{description: 'item one'}],
139
- additionalItems: {description: "mo' crap"},
140
- })
141
- first_subschema = schema.subschema_for_index(0)
142
- assert_instance_of(JSI::Schema, first_subschema)
143
- assert_equal('item one', first_subschema['description'])
144
- last_subschema = schema.subschema_for_index(1)
145
- assert_instance_of(JSI::Schema, last_subschema)
146
- assert_equal("mo' crap", last_subschema['description'])
147
- end
148
- end
149
- describe 'stringification' do
150
- let(:schema) do
151
- JSI::Schema.new({id: 'https://schemas.jsi.unth.net/test/stringification', type: 'object'})
152
- end
153
-
154
- it '#inspect' do
155
- assert_equal(%q(#<JSI::Schema schema_id=https://schemas.jsi.unth.net/test/stringification# #{<JSI::JSON::HashNode fragment="#"> "id" => "https://schemas.jsi.unth.net/test/stringification", "type" => "object"}>), schema.inspect)
156
- end
157
- it '#pretty_print' do
158
- assert_equal(%q(#<JSI::Schema schema_id=https://schemas.jsi.unth.net/test/stringification#
159
- #{<JSI::JSON::HashNode fragment="#">
160
- "id" => "https://schemas.jsi.unth.net/test/stringification",
161
- "type" => "object"
162
- }
163
- >).gsub(/^ /, ''), schema.pretty_inspect.chomp)
164
- end
165
- end
166
- describe 'validation' do
167
- let(:schema) { JSI::Schema.new({id: 'https://schemas.jsi.unth.net/test/validation', type: 'object'}) }
168
- describe 'without errors' do
169
- let(:instance) { {'foo' => 'bar'} }
170
- it '#fully_validate_instance' do
171
- assert_equal([], schema.fully_validate_instance(instance))
172
- end
173
- it '#validate_instance' do
174
- assert_equal(true, schema.validate_instance(instance))
175
- end
176
- it '#validate_instance!' do
177
- assert_equal(true, schema.validate_instance!(instance))
178
- end
179
- end
180
- describe 'with errors' do
181
- let(:instance) { ['no'] }
182
- it '#fully_validate_instance' do
183
- assert_equal(["The property '#/' of type array did not match the following type: object in schema https://schemas.jsi.unth.net/test/validation"], schema.fully_validate_instance(instance))
184
- end
185
- it '#validate_instance' do
186
- assert_equal(false, schema.validate_instance(instance))
187
- end
188
- it '#validate_instance!' do
189
- err = assert_raises(JSON::Schema::ValidationError) do
190
- schema.validate_instance!(instance)
191
- end
192
- assert_equal("The property '#/' of type array did not match the following type: object", err.message)
193
- end
194
- end
195
- end
196
- end