jsi 0.0.4 → 0.4.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +3 -1
  3. data/CHANGELOG.md +48 -0
  4. data/LICENSE.md +613 -0
  5. data/README.md +84 -45
  6. data/jsi.gemspec +11 -14
  7. data/lib/jsi.rb +31 -12
  8. data/lib/jsi/base.rb +310 -344
  9. data/lib/jsi/base/to_rb.rb +2 -0
  10. data/lib/jsi/jsi_coder.rb +91 -0
  11. data/lib/jsi/json-schema-fragments.rb +3 -135
  12. data/lib/jsi/json.rb +3 -0
  13. data/lib/jsi/json/node.rb +72 -197
  14. data/lib/jsi/json/pointer.rb +419 -0
  15. data/lib/jsi/metaschema.rb +7 -0
  16. data/lib/jsi/metaschema_node.rb +218 -0
  17. data/lib/jsi/pathed_node.rb +118 -0
  18. data/lib/jsi/schema.rb +168 -223
  19. data/lib/jsi/schema_classes.rb +158 -0
  20. data/lib/jsi/simple_wrap.rb +12 -0
  21. data/lib/jsi/typelike_modules.rb +71 -45
  22. data/lib/jsi/util.rb +47 -57
  23. data/lib/jsi/version.rb +1 -1
  24. data/lib/schemas/json-schema.org/draft-04/schema.rb +7 -0
  25. data/lib/schemas/json-schema.org/draft-06/schema.rb +7 -0
  26. data/resources/icons/AGPL-3.0.png +0 -0
  27. data/test/base_array_test.rb +210 -84
  28. data/test/base_hash_test.rb +201 -58
  29. data/test/base_test.rb +212 -121
  30. data/test/jsi_coder_test.rb +85 -0
  31. data/test/jsi_json_arraynode_test.rb +26 -25
  32. data/test/jsi_json_hashnode_test.rb +40 -39
  33. data/test/jsi_json_node_test.rb +95 -126
  34. data/test/jsi_json_pointer_test.rb +102 -0
  35. data/test/jsi_typelike_as_json_test.rb +53 -0
  36. data/test/metaschema_node_test.rb +19 -0
  37. data/test/schema_module_test.rb +21 -0
  38. data/test/schema_test.rb +109 -97
  39. data/test/spreedly_openapi_test.rb +8 -0
  40. data/test/test_helper.rb +42 -8
  41. data/test/util_test.rb +14 -14
  42. metadata +54 -25
  43. data/LICENSE.txt +0 -21
  44. data/lib/jsi/schema_instance_json_coder.rb +0 -83
  45. data/lib/jsi/struct_json_coder.rb +0 -30
  46. data/test/schema_instance_json_coder_test.rb +0 -121
  47. data/test/struct_json_coder_test.rb +0 -130
@@ -1,3 +1,3 @@
1
1
  module JSI
2
- VERSION = "0.0.4".freeze
2
+ VERSION = "0.4.0".freeze
3
3
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ schema_id = 'http://json-schema.org/draft-04/schema'
5
+ schema_content = ::JSON.parse(File.read(::JSON::Validator.validators[schema_id].metaschema))
6
+ JSONSchemaOrgDraft04 = MetaschemaNode.new(schema_content).jsi_schema_module
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSI
4
+ schema_id = 'http://json-schema.org/draft/schema' # I don't know why this is not http://json-schema.org/draft-06/schema
5
+ schema_content = ::JSON.parse(File.read(::JSON::Validator.validators[schema_id].metaschema))
6
+ JSONSchemaOrgDraft06 = MetaschemaNode.new(schema_content).jsi_schema_module
7
+ end
@@ -1,24 +1,32 @@
1
1
  require_relative 'test_helper'
2
2
 
3
- describe JSI::BaseArray do
4
- let(:document) do
5
- ['foo', {'lamp' => [3]}, ['q', 'r']]
6
- end
7
- let(:path) { [] }
8
- let(:instance) { JSI::JSON::Node.new_by_type(document, path) }
3
+ base = {
4
+ 'description' => 'named array schema',
5
+ 'type' => 'array',
6
+ 'items' => [
7
+ {'type' => 'string'},
8
+ {'type' => 'object'},
9
+ {'type' => 'array', 'items' => {}},
10
+ ],
11
+ }
12
+ NamedArrayInstance = JSI::Schema.new(base).jsi_schema_class
13
+ NamedIdArrayInstance = JSI::Schema.new({'$id' => 'https://schemas.jsi.unth.net/test/base/named_array_schema'}.merge(base)).jsi_schema_class
14
+
15
+ describe 'JSI::Base array' do
16
+ let(:instance) { ['foo', {'lamp' => [3]}, ['q', 'r'], {'four' => 4}] }
9
17
  let(:schema_content) do
10
18
  {
19
+ 'description' => 'hash schema',
11
20
  'type' => 'array',
12
21
  'items' => [
13
22
  {'type' => 'string'},
14
- {'type' => 'object', 'items' => {}},
15
- {'type' => 'array'},
23
+ {'type' => 'object'},
24
+ {'type' => 'array', 'items' => {}},
16
25
  ],
17
26
  }
18
27
  end
19
28
  let(:schema) { JSI::Schema.new(schema_content) }
20
- let(:class_for_schema) { JSI.class_for_schema(schema) }
21
- let(:subject) { class_for_schema.new(instance) }
29
+ let(:subject) { schema.new_jsi(instance) }
22
30
 
23
31
  describe '#[] with a default that is a basic type' do
24
32
  let(:schema_content) do
@@ -28,21 +36,21 @@ describe JSI::BaseArray do
28
36
  }
29
37
  end
30
38
  describe 'default value' do
31
- let(:document) { [1] }
39
+ let(:instance) { [1] }
32
40
  it 'returns the default value' do
33
41
  assert_equal('foo', subject[2])
34
42
  end
35
43
  end
36
44
  describe 'nondefault value (basic type)' do
37
- let(:document) { ['who'] }
45
+ let(:instance) { ['who'] }
38
46
  it 'returns the nondefault value' do
39
47
  assert_equal('who', subject[0])
40
48
  end
41
49
  end
42
50
  describe 'nondefault value (nonbasic type)' do
43
- let(:document) { [[2]] }
51
+ let(:instance) { [[2]] }
44
52
  it 'returns the nondefault value' do
45
- assert_instance_of(JSI.class_for_schema(schema['items']), subject[0])
53
+ assert_is_a(schema.items.jsi_schema_module, subject[0])
46
54
  assert_equal([2], subject[0].as_json)
47
55
  end
48
56
  end
@@ -55,22 +63,22 @@ describe JSI::BaseArray do
55
63
  }
56
64
  end
57
65
  describe 'default value' do
58
- let(:document) { [{'bar' => 3}] }
66
+ let(:instance) { [{'bar' => 3}] }
59
67
  it 'returns the default value' do
60
- assert_instance_of(JSI.class_for_schema(schema['items']), subject[1])
68
+ assert_is_a(schema.items.jsi_schema_module, subject[1])
61
69
  assert_equal({'foo' => 2}, subject[1].as_json)
62
70
  end
63
71
  end
64
72
  describe 'nondefault value (basic type)' do
65
- let(:document) { [true, 'who'] }
73
+ let(:instance) { [true, 'who'] }
66
74
  it 'returns the nondefault value' do
67
75
  assert_equal('who', subject[1])
68
76
  end
69
77
  end
70
78
  describe 'nondefault value (nonbasic type)' do
71
- let(:document) { [true, [2]] }
79
+ let(:instance) { [true, [2]] }
72
80
  it 'returns the nondefault value' do
73
- assert_instance_of(JSI.class_for_schema(schema['items']), subject[1])
81
+ assert_is_a(schema.items.jsi_schema_module, subject[1])
74
82
  assert_equal([2], subject[1].as_json)
75
83
  end
76
84
  end
@@ -82,110 +90,228 @@ describe JSI::BaseArray do
82
90
  subject[2] = {'y' => 'z'}
83
91
 
84
92
  assert_equal({'y' => 'z'}, subject[2].as_json)
85
- assert_instance_of(JSI.class_for_schema(schema.schema_node['items'][2]), orig_2)
86
- assert_instance_of(JSI.class_for_schema(schema.schema_node['items'][2]), subject[2])
93
+ assert_is_a(schema.items[2].jsi_schema_module, orig_2)
94
+ assert_is_a(schema.items[2].jsi_schema_module, subject[2])
87
95
  end
88
96
  it 'modifies the instance, visible to other references to the same instance' do
89
- orig_instance = subject.instance
97
+ orig_instance = subject.jsi_instance
90
98
 
91
99
  subject[2] = {'y' => 'z'}
92
100
 
93
- assert_equal(orig_instance, subject.instance)
94
- assert_equal({'y' => 'z'}, orig_instance[2].as_json)
95
- assert_equal({'y' => 'z'}, subject.instance[2].as_json)
96
- assert_equal(orig_instance.class, subject.instance.class)
101
+ assert_equal(orig_instance, subject.jsi_instance)
102
+ assert_equal({'y' => 'z'}, orig_instance[2])
103
+ assert_equal({'y' => 'z'}, subject.jsi_instance[2])
104
+ assert_equal(orig_instance.class, subject.jsi_instance.class)
97
105
  end
98
106
  describe 'when the instance is not arraylike' do
99
107
  let(:instance) { nil }
100
108
  it 'errors' do
101
109
  err = assert_raises(NoMethodError) { subject[2] = 0 }
102
- assert_match(%r(\Aundefined method `\[\]=' for #<JSI::SchemaClasses::X.*>\z), err.message)
110
+ assert_equal("cannot assign subcript (using token: 2) to instance: nil", err.message)
111
+ end
112
+ end
113
+ describe '#inspect' do
114
+ it 'inspects' do
115
+ assert_equal("#[<JSI> \"foo\", \#{<JSI> \"lamp\" => [3]}, #[<JSI> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
116
+ end
117
+ end
118
+ describe '#pretty_print' do
119
+ it 'pretty_prints' do
120
+ assert_equal("#[<JSI> \"foo\", \#{<JSI> \"lamp\" => [3]}, #[<JSI> \"q\", \"r\"], {\"four\"=>4}]\n", subject.pretty_inspect)
121
+ end
122
+ end
123
+ describe '#inspect SortOfArray' do
124
+ let(:subject) { schema.new_jsi(SortOfArray.new(instance)) }
125
+ it 'inspects' do
126
+ assert_equal("#[<JSI SortOfArray> \"foo\", \#{<JSI> \"lamp\" => [3]}, #[<JSI> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
127
+ end
128
+ end
129
+ describe '#pretty_print SortOfArray' do
130
+ let(:subject) { schema.new_jsi(SortOfArray.new(instance)) }
131
+ it 'pretty_prints' do
132
+ assert_equal("#[<JSI SortOfArray>\n \"foo\",\n \#{<JSI> \"lamp\" => [3]},\n #[<JSI> \"q\", \"r\"],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
133
+ end
134
+ end
135
+ describe '#inspect named' do
136
+ let(:subject) { NamedArrayInstance.new(instance) }
137
+ it 'inspects' do
138
+ assert_equal("#[<NamedArrayInstance> \"foo\", \#{<JSI> \"lamp\" => [3]}, #[<JSI> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
139
+ end
140
+ end
141
+ describe '#pretty_print named' do
142
+ let(:subject) { NamedArrayInstance.new(instance) }
143
+ it 'inspects' do
144
+ assert_equal("#[<NamedArrayInstance>\n \"foo\",\n \#{<JSI> \"lamp\" => [3]},\n #[<JSI> \"q\", \"r\"],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
145
+ end
146
+ end
147
+ describe '#inspect named SortOfArray' do
148
+ let(:subject) { NamedArrayInstance.new(SortOfArray.new(instance)) }
149
+ it 'inspects' do
150
+ assert_equal("#[<NamedArrayInstance SortOfArray> \"foo\", \#{<JSI> \"lamp\" => [3]}, #[<JSI> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
151
+ end
152
+ end
153
+ describe '#pretty_print named SortOfArray' do
154
+ let(:subject) { NamedArrayInstance.new(SortOfArray.new(instance)) }
155
+ it 'inspects' do
156
+ assert_equal("#[<NamedArrayInstance SortOfArray>\n \"foo\",\n \#{<JSI> \"lamp\" => [3]},\n #[<JSI> \"q\", \"r\"],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
157
+ end
158
+ end
159
+ describe '#inspect named with id' do
160
+ let(:subject) { NamedIdArrayInstance.new(instance) }
161
+ it 'inspects' do
162
+ assert_equal("#[<NamedIdArrayInstance> \"foo\", \#{<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/1)> \"lamp\" => [3]}, #[<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/2)> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
163
+ end
164
+ end
165
+ describe '#pretty_print named with id' do
166
+ let(:subject) { NamedIdArrayInstance.new(instance) }
167
+ it 'inspects' do
168
+ assert_equal("#[<NamedIdArrayInstance>\n \"foo\",\n \#{<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/1)>\n \"lamp\" => [3]\n },\n #[<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/2)>\n \"q\",\n \"r\"\n ],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
169
+ end
170
+ end
171
+ describe '#inspect named with id SortOfArray' do
172
+ let(:subject) { NamedIdArrayInstance.new(SortOfArray.new(instance)) }
173
+ it 'inspects' do
174
+ assert_equal("#[<NamedIdArrayInstance SortOfArray> \"foo\", \#{<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/1)> \"lamp\" => [3]}, #[<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/2)> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
175
+ end
176
+ end
177
+ describe '#pretty_print named with id SortOfArray' do
178
+ let(:subject) { NamedIdArrayInstance.new(SortOfArray.new(instance)) }
179
+ it 'inspects' do
180
+ assert_equal("#[<NamedIdArrayInstance SortOfArray>\n \"foo\",\n \#{<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/1)>\n \"lamp\" => [3]\n },\n #[<JSI (https://schemas.jsi.unth.net/test/base/named_array_schema#/items/2)>\n \"q\",\n \"r\"\n ],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
181
+ end
182
+ end
183
+ describe '#inspect with id' do
184
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_array_test/withid', 'items' => [{}, {}, {}]} }
185
+ let(:subject) { schema.new_jsi(instance) }
186
+ it 'inspects' do
187
+ assert_equal("#[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#)> \"foo\", \#{<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/1)> \"lamp\" => [3]}, #[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/2)> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
188
+ end
189
+ end
190
+ describe '#pretty_print with id' do
191
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_array_test/withid', 'items' => [{}, {}, {}]} }
192
+ let(:subject) { schema.new_jsi(instance) }
193
+ it 'pretty prints' do
194
+ assert_equal("#[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#)>\n \"foo\",\n \#{<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/1)>\n \"lamp\" => [3]\n },\n #[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/2)>\n \"q\",\n \"r\"\n ],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
195
+ end
196
+ end
197
+ describe '#inspect with id SortOfArray' do
198
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_array_test/withid', 'items' => [{}, {}, {}]} }
199
+ let(:subject) { schema.new_jsi(SortOfArray.new(instance)) }
200
+ it 'inspects' do
201
+ assert_equal("#[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#) SortOfArray> \"foo\", \#{<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/1)> \"lamp\" => [3]}, #[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/2)> \"q\", \"r\"], {\"four\"=>4}]", subject.inspect)
202
+ end
203
+ end
204
+ describe '#pretty_print with id SortOfArray' do
205
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_array_test/withid', 'items' => [{}, {}, {}]} }
206
+ let(:subject) { schema.new_jsi(SortOfArray.new(instance)) }
207
+ it 'inspects' do
208
+ assert_equal("#[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#) SortOfArray>\n \"foo\",\n \#{<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/1)>\n \"lamp\" => [3]\n },\n #[<JSI (https://schemas.jsi.unth.net/base_array_test/withid#/items/2)>\n \"q\",\n \"r\"\n ],\n {\"four\"=>4}\n]\n", subject.pretty_inspect)
209
+ end
210
+ end
211
+ describe '#inspect Node' do
212
+ let(:subject) { schema.new_jsi(JSI::JSON::Node.new_doc(instance)) }
213
+ it 'inspects' do
214
+ assert_equal("#[<JSI JSI::JSON::ArrayNode #> \"foo\", \#{<JSI JSI::JSON::HashNode #/1> \"lamp\" => #[<JSI::JSON::ArrayNode #/1/lamp> 3]}, #[<JSI JSI::JSON::ArrayNode #/2> \"q\", \"r\"], \#{<JSI::JSON::HashNode #/3> \"four\" => 4}]", subject.inspect)
215
+ end
216
+ end
217
+ describe '#pretty_print Node' do
218
+ let(:subject) { schema.new_jsi(JSI::JSON::Node.new_doc(instance)) }
219
+ it 'pretty_prints' do
220
+ assert_equal("#[<JSI JSI::JSON::ArrayNode #>\n \"foo\",\n \#{<JSI JSI::JSON::HashNode #/1>\n \"lamp\" => #[<JSI::JSON::ArrayNode #/1/lamp> 3]\n },\n #[<JSI JSI::JSON::ArrayNode #/2> \"q\", \"r\"],\n \#{<JSI::JSON::HashNode #/3> \"four\" => 4}\n]\n", subject.pretty_inspect)
103
221
  end
104
222
  end
105
223
  end
106
224
  # these methods just delegate to Array so not going to test excessively
107
225
  describe 'index only methods' do
108
- it('#each_index') { assert_equal([0, 1, 2], subject.each_index.to_a) }
109
- it('#empty?') { assert_equal(false, subject.empty?) }
110
- it('#length') { assert_equal(3, subject.length) }
111
- it('#size') { assert_equal(3, subject.size) }
226
+ it('#each_index') { assert_equal([0, 1, 2, 3], subject.each_index.to_a) }
227
+ it('#empty?') { assert_equal(false, subject.empty?) }
228
+ it('#length') { assert_equal(4, subject.length) }
229
+ it('#size') { assert_equal(4, subject.size) }
112
230
  end
113
231
  describe 'index + element methods' do
114
- it('#|') { assert_equal(['foo', subject[1], subject[2], 0], subject | [0]) }
115
- it('#&') { assert_equal(['foo'], subject & ['foo']) }
116
- it('#*') { assert_equal(subject.to_a, subject * 1) }
117
- it('#+') { assert_equal(subject.to_a, subject + []) }
118
- it('#-') { assert_equal([subject[1], subject[2]], subject - ['foo']) }
119
- it('#<=>') { assert_equal(1, subject <=> []) }
120
- it('#<=>') { assert_equal(-1, [] <=> subject) }
232
+ it('#|') { assert_equal(['foo', subject[1], subject[2], subject[3], 0], subject | [0]) }
233
+ it('#&') { assert_equal(['foo'], subject & ['foo']) }
234
+ it('#*') { assert_equal(subject.to_a, subject * 1) }
235
+ it('#+') { assert_equal(subject.to_a, subject + []) }
236
+ it('#-') { assert_equal([subject[1], subject[2], subject[3]], subject - ['foo']) }
237
+ it('#<=>') { assert_equal(1, subject <=> []) }
238
+ it('#<=>') { assert_equal(-1, [] <=> subject) }
121
239
  require 'abbrev'
122
- it('#abbrev') { assert_equal({'a' => 'a'}, class_for_schema.new(['a']).abbrev) }
123
- it('#assoc') { assert_equal(['q', 'r'], subject.instance.assoc('q')) }
124
- it('#at') { assert_equal('foo', subject.at(0)) }
125
- it('#bsearch') { assert_equal(nil, subject.bsearch { false }) }
126
- it('#bsearch_index') { assert_equal(nil, subject.bsearch_index { false }) } if [].respond_to?(:bsearch_index)
127
- it('#combination') { assert_equal([['foo'], [subject[1]], [subject[2]]], subject.combination(1).to_a) }
128
- it('#count') { assert_equal(1, subject.count('foo')) }
129
- it('#cycle') { assert_equal(subject.to_a, subject.cycle(1).to_a) }
130
- it('#dig') { assert_equal(3, subject.dig(1, 'lamp', 0)) } if [].respond_to?(:dig)
131
- it('#drop') { assert_equal([subject[2]], subject.drop(2)) }
132
- it('#drop_while') { assert_equal([subject[1], subject[2]], subject.drop_while { |e| e == 'foo' }) }
133
- it('#fetch') { assert_equal('foo', subject.fetch(0)) }
134
- it('#find_index') { assert_equal(0, subject.find_index { true }) }
135
- it('#first') { assert_equal('foo', subject.first) }
136
- it('#include?') { assert_equal(true, subject.include?('foo')) }
137
- it('#index') { assert_equal(0, subject.index('foo')) }
138
- it('#join') { assert_equal('a b', class_for_schema.new(['a', 'b']).join(' ')) }
139
- it('#last') { assert_equal(subject[2], subject.last) }
140
- it('#pack') { assert_equal(' ', class_for_schema.new([32]).pack('c')) }
141
- it('#permutation') { assert_equal([['foo'], [subject[1]], [subject[2]]], subject.permutation(1).to_a) }
142
- it('#product') { assert_equal([], subject.product([])) }
240
+ it('#abbrev') { assert_equal({'a' => 'a'}, schema.new_jsi(['a']).abbrev) }
241
+ it('#assoc') { assert_equal(['q', 'r'], subject.assoc('q')) }
242
+ it('#at') { assert_equal('foo', subject.at(0)) }
243
+ it('#bsearch') { assert_equal(nil, subject.bsearch { false }) }
244
+ it('#bsearch_index') { assert_equal(nil, subject.bsearch_index { false }) } if [].respond_to?(:bsearch_index)
245
+ it('#combination') { assert_equal([['foo'], [subject[1]], [subject[2]], [subject[3]]], subject.combination(1).to_a) }
246
+ it('#count') { assert_equal(1, subject.count('foo')) }
247
+ it('#cycle') { assert_equal(subject.to_a, subject.cycle(1).to_a) }
248
+ it('#dig') { assert_equal(3, subject.dig(1, 'lamp', 0)) } if [].respond_to?(:dig)
249
+ it('#drop') { assert_equal([subject[2], subject[3]], subject.drop(2)) }
250
+ it('#drop_while') { assert_equal([subject[1], subject[2], subject[3]], subject.drop_while { |e| e == 'foo' }) }
251
+ it('#fetch') { assert_equal('foo', subject.fetch(0)) }
252
+ it('#find_index') { assert_equal(0, subject.find_index { true }) }
253
+ it('#first') { assert_equal('foo', subject.first) }
254
+ it('#include?') { assert_equal(true, subject.include?('foo')) }
255
+ it('#index') { assert_equal(0, subject.index('foo')) }
256
+ it('#join') { assert_equal('a b', schema.new_jsi(['a', 'b']).join(' ')) }
257
+ it('#last') { assert_equal(subject[3], subject.last) }
258
+ it('#pack') { assert_equal(' ', schema.new_jsi([32]).pack('c')) }
259
+ it('#permutation') { assert_equal([['foo'], [subject[1]], [subject[2]], [subject[3]]], subject.permutation(1).to_a) }
260
+ it('#product') { assert_equal([], subject.product([])) }
143
261
  # due to differences in implementation between #assoc and #rassoc, the reason for which
144
262
  # I cannot begin to fathom, assoc works but rassoc does not because rassoc has different
145
263
  # type checking than assoc for the array(like) array elements.
146
264
  # compare:
147
265
  # assoc: https://github.com/ruby/ruby/blob/v2_5_0/array.c#L3780-L3813
148
266
  # rassoc: https://github.com/ruby/ruby/blob/v2_5_0/array.c#L3815-L3847
149
- # for this reason, rassoc is NOT defined on Arraylike and #content must be called.
150
- it('#rassoc') { assert_equal(['q', 'r'], subject.instance.content.rassoc('r')) }
267
+ # for this reason, rassoc is NOT defined on Arraylike and we call #jsi_instance to use it.
268
+ it('#rassoc') { assert_equal(['q', 'r'], subject.jsi_instance.rassoc('r')) }
151
269
  it('#repeated_combination') { assert_equal([[]], subject.repeated_combination(0).to_a) }
152
270
  it('#repeated_permutation') { assert_equal([[]], subject.repeated_permutation(0).to_a) }
153
- it('#reverse') { assert_equal([subject[2], subject[1], 'foo'], subject.reverse) }
154
- it('#reverse_each') { assert_equal([subject[2], subject[1], 'foo'], subject.reverse_each.to_a) }
155
- it('#rindex') { assert_equal(0, subject.rindex('foo')) }
156
- it('#rotate') { assert_equal([subject[1], subject[2], 'foo'], subject.rotate) }
157
- it('#sample') { assert_equal('a', class_for_schema.new(['a']).sample) }
158
- it('#shelljoin') { assert_equal('a', class_for_schema.new(['a']).shelljoin) } if [].respond_to?(:shelljoin)
159
- it('#shuffle') { assert_equal(3, subject.shuffle.size) }
160
- it('#slice') { assert_equal(['foo'], subject.slice(0, 1)) }
161
- it('#sort') { assert_equal(['a'], class_for_schema.new(['a']).sort) }
162
- it('#take') { assert_equal(['foo'], subject.take(1)) }
163
- it('#take_while') { assert_equal([], subject.take_while { false }) }
164
- it('#transpose') { assert_equal([], class_for_schema.new([]).transpose) }
165
- it('#uniq') { assert_equal(subject.to_a, subject.uniq) }
166
- it('#values_at') { assert_equal(['foo'], subject.values_at(0)) }
167
- it('#zip') { assert_equal([['foo', 'foo'], [subject[1], subject[1]], [subject[2], subject[2]]], subject.zip(subject)) }
271
+ it('#reverse') { assert_equal([subject[3], subject[2], subject[1], 'foo'], subject.reverse) }
272
+ it('#reverse_each') { assert_equal([subject[3], subject[2], subject[1], 'foo'], subject.reverse_each.to_a) }
273
+ it('#rindex') { assert_equal(0, subject.rindex('foo')) }
274
+ it('#rotate') { assert_equal([subject[1], subject[2], subject[3], 'foo'], subject.rotate) }
275
+ it('#sample') { assert_equal('a', schema.new_jsi(['a']).sample) }
276
+ it('#shelljoin') { assert_equal('a', schema.new_jsi(['a']).shelljoin) } if [].respond_to?(:shelljoin)
277
+ it('#shuffle') { assert_equal(4, subject.shuffle.size) }
278
+ it('#slice') { assert_equal(['foo'], subject.slice(0, 1)) }
279
+ it('#sort') { assert_equal(['a'], schema.new_jsi(['a']).sort) }
280
+ it('#take') { assert_equal(['foo'], subject.take(1)) }
281
+ it('#take_while') { assert_equal([], subject.take_while { false }) }
282
+ it('#transpose') { assert_equal([], schema.new_jsi([]).transpose) }
283
+ it('#uniq') { assert_equal(subject.to_a, subject.uniq) }
284
+ it('#values_at') { assert_equal(['foo'], subject.values_at(0)) }
285
+ it('#zip') { assert_equal([['foo', 'foo'], [subject[1], subject[1]], [subject[2], subject[2]], [subject[3], subject[3]]], subject.zip(subject)) }
286
+ end
287
+ describe 'with an instance that has to_ary but not other ary instance methods' do
288
+ let(:instance) { SortOfArray.new(['foo', {'lamp' => SortOfArray.new([3])}, SortOfArray.new(['q', 'r'])]) }
289
+ describe 'delegating instance methods to #to_ary' do
290
+ it('#each_index') { assert_equal([0, 1, 2], subject.each_index.to_a) }
291
+ it('#size') { assert_equal(3, subject.size) }
292
+ it('#count') { assert_equal(1, subject.count('foo')) }
293
+ it('#slice') { assert_equal(['foo'], subject.slice(0, 1)) }
294
+ it('#[]') { assert_equal(SortOfArray.new(['q', 'r']), subject[2].jsi_instance) }
295
+ it('#as_json') { assert_equal(['foo', {'lamp' => [3]}, ['q', 'r']], subject.as_json) }
296
+ end
168
297
  end
169
298
  describe 'modified copy methods' do
170
- it('#reject') { assert_equal(class_for_schema.new(JSI::JSON::ArrayNode.new(['foo'], [])), subject.reject { |e| e != 'foo' }) }
299
+ it('#reject') { assert_equal(schema.new_jsi(['foo']), subject.reject { |e| e != 'foo' }) }
171
300
  it('#reject block var') do
172
301
  subj_a = subject.to_a
173
302
  subject.reject { |e| assert_equal(e, subj_a.shift) }
174
303
  end
175
- it('#select') { assert_equal(class_for_schema.new(JSI::JSON::ArrayNode.new(['foo'], [])), subject.select { |e| e == 'foo' }) }
304
+ it('#select') { assert_equal(schema.new_jsi(['foo']), subject.select { |e| e == 'foo' }) }
176
305
  it('#select block var') do
177
306
  subj_a = subject.to_a
178
307
  subject.select { |e| assert_equal(e, subj_a.shift) }
179
308
  end
180
309
  it('#compact') { assert_equal(subject, subject.compact) }
181
310
  describe 'at a depth' do
182
- let(:document) { [['b', 'q'], {'c' => ['d', 'e']}] }
183
- let(:path) { ['1', 'c'] }
184
311
  it('#select') do
185
- selected = subject.select { |e| e == 'd' }
186
- equivalent_node = JSI::JSON::ArrayNode.new([['b', 'q'], {'c' => ['d']}], path)
187
- equivalent = class_for_schema.new(equivalent_node)
188
- assert_equal(equivalent, selected)
312
+ expected = schema.new_jsi(['foo', {'lamp' => [3]}, ['r'], {'four' => 4}])[2]
313
+ actual = subject[2].select { |e| e == 'r' }
314
+ assert_equal(expected, actual)
189
315
  end
190
316
  end
191
317
  end
@@ -1,13 +1,21 @@
1
1
  require_relative 'test_helper'
2
2
 
3
- describe JSI::BaseHash do
4
- let(:document) do
5
- {'foo' => {'x' => 'y'}, 'bar' => [9], 'baz' => true}
6
- end
7
- let(:path) { [] }
8
- let(:instance) { JSI::JSON::Node.new_by_type(document, path) }
3
+ base = {
4
+ 'description' => 'named hash schema',
5
+ 'type' => 'object',
6
+ 'properties' => {
7
+ 'foo' => {'type' => 'object'},
8
+ 'bar' => {},
9
+ },
10
+ }
11
+ NamedHashInstance = JSI::Schema.new(base).jsi_schema_class
12
+ NamedIdHashInstance = JSI::Schema.new({'$id' => 'https://schemas.jsi.unth.net/test/base/named_hash_schema'}.merge(base)).jsi_schema_class
13
+
14
+ describe 'JSI::Base hash' do
15
+ let(:instance) { {'foo' => {'x' => 'y'}, 'bar' => [9], 'baz' => [true]} }
9
16
  let(:schema_content) do
10
17
  {
18
+ 'description' => 'hash schema',
11
19
  'type' => 'object',
12
20
  'properties' => {
13
21
  'foo' => {'type' => 'object'},
@@ -16,10 +24,9 @@ describe JSI::BaseHash do
16
24
  }
17
25
  end
18
26
  let(:schema) { JSI::Schema.new(schema_content) }
19
- let(:class_for_schema) { JSI.class_for_schema(schema) }
20
- let(:subject) { class_for_schema.new(instance) }
27
+ let(:subject) { schema.new_jsi(instance) }
21
28
 
22
- describe '#[] with a default that is a basic type' do
29
+ describe '#[] with a schema default that is a basic type' do
23
30
  let(:schema_content) do
24
31
  {
25
32
  'type' => 'object',
@@ -29,26 +36,26 @@ describe JSI::BaseHash do
29
36
  }
30
37
  end
31
38
  describe 'default value' do
32
- let(:document) { {'bar' => 3} }
39
+ let(:instance) { {'bar' => 3} }
33
40
  it 'returns the default value' do
34
41
  assert_equal('foo', subject.foo)
35
42
  end
36
43
  end
37
44
  describe 'nondefault value (basic type)' do
38
- let(:document) { {'foo' => 'who'} }
45
+ let(:instance) { {'foo' => 'who'} }
39
46
  it 'returns the nondefault value' do
40
47
  assert_equal('who', subject.foo)
41
48
  end
42
49
  end
43
50
  describe 'nondefault value (nonbasic type)' do
44
- let(:document) { {'foo' => [2]} }
51
+ let(:instance) { {'foo' => [2]} }
45
52
  it 'returns the nondefault value' do
46
- assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
53
+ assert_is_a(schema.properties['foo'].jsi_schema_module, subject.foo)
47
54
  assert_equal([2], subject.foo.as_json)
48
55
  end
49
56
  end
50
57
  end
51
- describe '#[] with a default that is a nonbasic type' do
58
+ describe '#[] with a schema default that is a nonbasic type' do
52
59
  let(:schema_content) do
53
60
  {
54
61
  'type' => 'object',
@@ -58,26 +65,43 @@ describe JSI::BaseHash do
58
65
  }
59
66
  end
60
67
  describe 'default value' do
61
- let(:document) { {'bar' => 3} }
68
+ let(:instance) { {'bar' => 3} }
62
69
  it 'returns the default value' do
63
- assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
70
+ assert_is_a(schema.properties['foo'].jsi_schema_module, subject.foo)
64
71
  assert_equal({'foo' => 2}, subject.foo.as_json)
65
72
  end
66
73
  end
67
74
  describe 'nondefault value (basic type)' do
68
- let(:document) { {'foo' => 'who'} }
75
+ let(:instance) { {'foo' => 'who'} }
69
76
  it 'returns the nondefault value' do
70
77
  assert_equal('who', subject.foo)
71
78
  end
72
79
  end
73
80
  describe 'nondefault value (nonbasic type)' do
74
- let(:document) { {'foo' => [2]} }
81
+ let(:instance) { {'foo' => [2]} }
75
82
  it 'returns the nondefault value' do
76
- assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
83
+ assert_is_a(schema.properties['foo'].jsi_schema_module, subject.foo)
77
84
  assert_equal([2], subject.foo.as_json)
78
85
  end
79
86
  end
80
87
  end
88
+ describe '#[] with a hash default that is a nonbasic type' do
89
+ let(:schema_content) do
90
+ {
91
+ 'type' => 'object',
92
+ 'properties' => {
93
+ 'foo' => {},
94
+ },
95
+ }
96
+ end
97
+ describe 'default value' do
98
+ let(:instance) { Hash.new({'foo' => 2}).merge({'bar' => 3}) }
99
+ it 'returns the default value' do
100
+ assert_is_a(Hash, subject.foo)
101
+ assert_equal({'foo' => 2}, subject.foo)
102
+ end
103
+ end
104
+ end
81
105
  describe 'hashlike []=' do
82
106
  it 'sets a property' do
83
107
  orig_foo = subject['foo']
@@ -85,8 +109,8 @@ describe JSI::BaseHash do
85
109
  subject['foo'] = {'y' => 'z'}
86
110
 
87
111
  assert_equal({'y' => 'z'}, subject['foo'].as_json)
88
- assert_instance_of(JSI.class_for_schema(schema.schema_node['properties']['foo']), orig_foo)
89
- assert_instance_of(JSI.class_for_schema(schema.schema_node['properties']['foo']), subject['foo'])
112
+ assert_is_a(schema.properties['foo'].jsi_schema_module, orig_foo)
113
+ assert_is_a(schema.properties['foo'].jsi_schema_module, subject['foo'])
90
114
  end
91
115
  it 'sets a property to a schema instance with a different schema' do
92
116
  assert(subject['foo'])
@@ -96,11 +120,11 @@ describe JSI::BaseHash do
96
120
  # the content of the subscripts' instances is the same but the subscripts' classes are different
97
121
  assert_equal([9], subject['foo'].as_json)
98
122
  assert_equal([9], subject['bar'].as_json)
99
- assert_instance_of(JSI.class_for_schema(schema.schema_node['properties']['foo']), subject['foo'])
100
- assert_instance_of(JSI.class_for_schema(schema.schema_node['properties']['bar']), subject['bar'])
123
+ assert_is_a(schema.properties['foo'].jsi_schema_module, subject['foo'])
124
+ assert_is_a(schema.properties['bar'].jsi_schema_module, subject['bar'])
101
125
  end
102
126
  it 'sets a property to a schema instance with the same schema' do
103
- other_subject = class_for_schema.new(JSI::JSON::Node.new_doc({'foo' => {'x' => 'y'}, 'bar' => [9], 'baz' => true}))
127
+ other_subject = schema.new_jsi({'foo' => {'x' => 'y'}, 'bar' => [9], 'baz' => [true]})
104
128
  # Given
105
129
  assert_equal(other_subject, subject)
106
130
 
@@ -114,20 +138,130 @@ describe JSI::BaseHash do
114
138
  refute_equal(other_subject['foo'].object_id, subject['foo'].object_id)
115
139
  end
116
140
  it 'modifies the instance, visible to other references to the same instance' do
117
- orig_instance = subject.instance
141
+ orig_instance = subject.jsi_instance
118
142
 
119
143
  subject['foo'] = {'y' => 'z'}
120
144
 
121
- assert_equal(orig_instance, subject.instance)
122
- assert_equal({'y' => 'z'}, orig_instance['foo'].as_json)
123
- assert_equal({'y' => 'z'}, subject.instance['foo'].as_json)
124
- assert_equal(orig_instance.class, subject.instance.class)
145
+ assert_equal(orig_instance, subject.jsi_instance)
146
+ assert_equal({'y' => 'z'}, orig_instance['foo'])
147
+ assert_equal({'y' => 'z'}, subject.jsi_instance['foo'])
148
+ assert_equal(orig_instance.class, subject.jsi_instance.class)
125
149
  end
126
150
  describe 'when the instance is not hashlike' do
127
151
  let(:instance) { nil }
128
152
  it 'errors' do
129
153
  err = assert_raises(NoMethodError) { subject['foo'] = 0 }
130
- assert_match(%r(\Aundefined method `\[\]=' for #<JSI::SchemaClasses::.*>\z), err.message)
154
+ assert_equal('cannot assign subcript (using token: "foo") to instance: nil', err.message)
155
+ end
156
+ end
157
+ describe '#inspect' do
158
+ it 'inspects' do
159
+ assert_equal("\#{<JSI> \"foo\" => \#{<JSI> \"x\" => \"y\"}, \"bar\" => #[<JSI> 9], \"baz\" => [true]}", subject.inspect)
160
+ end
161
+ end
162
+ describe '#pretty_print' do
163
+ it 'pretty_prints' do
164
+ assert_equal("\#{<JSI> \"foo\" => \#{<JSI> \"x\" => \"y\"}, \"bar\" => #[<JSI> 9], \"baz\" => [true]}\n", subject.pretty_inspect)
165
+ end
166
+ end
167
+ describe '#inspect SortOfHash' do
168
+ let(:subject) { schema.new_jsi(SortOfHash.new(instance)) }
169
+ it 'inspects' do
170
+ assert_equal("\#{<JSI SortOfHash> \"foo\" => \#{<JSI> \"x\" => \"y\"}, \"bar\" => #[<JSI> 9], \"baz\" => [true]}", subject.inspect)
171
+ end
172
+ end
173
+ describe '#pretty_print SortOfHash' do
174
+ let(:subject) { schema.new_jsi(SortOfHash.new(instance)) }
175
+ it 'pretty_prints' do
176
+ assert_equal("\#{<JSI SortOfHash>\n \"foo\" => \#{<JSI> \"x\" => \"y\"},\n \"bar\" => #[<JSI> 9],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
177
+ end
178
+ end
179
+ describe '#inspect named' do
180
+ let(:subject) { NamedHashInstance.new(instance) }
181
+ it 'inspects' do
182
+ assert_equal("\#{<NamedHashInstance> \"foo\" => \#{<JSI> \"x\" => \"y\"}, \"bar\" => #[<JSI> 9], \"baz\" => [true]}", subject.inspect)
183
+ end
184
+ end
185
+ describe '#pretty_print named' do
186
+ let(:subject) { NamedHashInstance.new(instance) }
187
+ it 'inspects' do
188
+ assert_equal("\#{<NamedHashInstance>\n \"foo\" => \#{<JSI> \"x\" => \"y\"},\n \"bar\" => #[<JSI> 9],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
189
+ end
190
+ end
191
+ describe '#inspect named SortOfHash' do
192
+ let(:subject) { NamedHashInstance.new(SortOfHash.new(instance)) }
193
+ it 'inspects' do
194
+ assert_equal("\#{<NamedHashInstance SortOfHash> \"foo\" => \#{<JSI> \"x\" => \"y\"}, \"bar\" => #[<JSI> 9], \"baz\" => [true]}", subject.inspect)
195
+ end
196
+ end
197
+ describe '#pretty_print named SortOfHash' do
198
+ let(:subject) { NamedHashInstance.new(SortOfHash.new(instance)) }
199
+ it 'inspects' do
200
+ assert_equal("\#{<NamedHashInstance SortOfHash>\n \"foo\" => \#{<JSI> \"x\" => \"y\"},\n \"bar\" => #[<JSI> 9],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
201
+ end
202
+ end
203
+ describe '#inspect named with id' do
204
+ let(:subject) { NamedIdHashInstance.new(instance) }
205
+ it 'inspects' do
206
+ assert_equal("\#{<NamedIdHashInstance> \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/foo)> \"x\" => \"y\"}, \"bar\" => #[<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/bar)> 9], \"baz\" => [true]}", subject.inspect)
207
+ end
208
+ end
209
+ describe '#pretty_print named with id' do
210
+ let(:subject) { NamedIdHashInstance.new(instance) }
211
+ it 'inspects' do
212
+ assert_equal("\#{<NamedIdHashInstance>\n \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/foo)>\n \"x\" => \"y\"\n },\n \"bar\" => #[<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/bar)>\n 9\n ],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
213
+ end
214
+ end
215
+ describe '#inspect named SortOfHash with id' do
216
+ let(:subject) { NamedIdHashInstance.new(SortOfHash.new(instance)) }
217
+ it 'inspects' do
218
+ assert_equal("\#{<NamedIdHashInstance SortOfHash> \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/foo)> \"x\" => \"y\"}, \"bar\" => #[<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/bar)> 9], \"baz\" => [true]}", subject.inspect)
219
+ end
220
+ end
221
+ describe '#pretty_print named with id SortOfHash' do
222
+ let(:subject) { NamedIdHashInstance.new(SortOfHash.new(instance)) }
223
+ it 'inspects' do
224
+ assert_equal("\#{<NamedIdHashInstance SortOfHash>\n \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/foo)>\n \"x\" => \"y\"\n },\n \"bar\" => #[<JSI (https://schemas.jsi.unth.net/test/base/named_hash_schema#/properties/bar)>\n 9\n ],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
225
+ end
226
+ end
227
+ describe '#inspect with id' do
228
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_hash_test/withid', 'properties' => {'foo' => {}, 'bar' => {}}} }
229
+ let(:subject) { schema.new_jsi(instance) }
230
+ it 'inspects' do
231
+ assert_equal("\#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#)> \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/foo)> \"x\" => \"y\"}, \"bar\" => #[<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/bar)> 9], \"baz\" => [true]}", subject.inspect)
232
+ end
233
+ end
234
+ describe '#pretty_print with id' do
235
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_hash_test/withid', 'properties' => {'foo' => {}, 'bar' => {}}} }
236
+ let(:subject) { schema.new_jsi(instance) }
237
+ it 'inspects' do
238
+ assert_equal("\#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#)>\n \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/foo)>\n \"x\" => \"y\"\n },\n \"bar\" => #[<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/bar)>\n 9\n ],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
239
+ end
240
+ end
241
+ describe '#inspect with id SortOfHash' do
242
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_hash_test/withid', 'properties' => {'foo' => {}, 'bar' => {}}} }
243
+ let(:subject) { schema.new_jsi(SortOfHash.new(instance)) }
244
+ it 'inspects' do
245
+ assert_equal("\#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#) SortOfHash> \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/foo)> \"x\" => \"y\"}, \"bar\" => #[<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/bar)> 9], \"baz\" => [true]}", subject.inspect)
246
+ end
247
+ end
248
+ describe '#pretty_print with id SortOfHash' do
249
+ let(:schema_content) { {'$id' => 'https://schemas.jsi.unth.net/base_hash_test/withid', 'properties' => {'foo' => {}, 'bar' => {}}} }
250
+ let(:subject) { schema.new_jsi(SortOfHash.new(instance)) }
251
+ it 'inspects' do
252
+ assert_equal("\#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#) SortOfHash>\n \"foo\" => \#{<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/foo)>\n \"x\" => \"y\"\n },\n \"bar\" => #[<JSI (https://schemas.jsi.unth.net/base_hash_test/withid#/properties/bar)>\n 9\n ],\n \"baz\" => [true]\n}\n", subject.pretty_inspect)
253
+ end
254
+ end
255
+ describe '#inspect Node' do
256
+ let(:subject) { schema.new_jsi(JSI::JSON::Node.new_doc(instance)) }
257
+ it 'inspects' do
258
+ assert_equal("\#{<JSI JSI::JSON::HashNode #> \"foo\" => \#{<JSI JSI::JSON::HashNode #/foo> \"x\" => \"y\"}, \"bar\" => #[<JSI JSI::JSON::ArrayNode #/bar> 9], \"baz\" => #[<JSI::JSON::ArrayNode #/baz> true]}", subject.inspect)
259
+ end
260
+ end
261
+ describe '#pretty_print Node' do
262
+ let(:subject) { schema.new_jsi(JSI::JSON::Node.new_doc(instance)) }
263
+ it 'pretty_prints' do
264
+ assert_equal("\#{<JSI JSI::JSON::HashNode #>\n \"foo\" => \#{<JSI JSI::JSON::HashNode #/foo> \"x\" => \"y\"},\n \"bar\" => #[<JSI JSI::JSON::ArrayNode #/bar> 9],\n \"baz\" => #[<JSI::JSON::ArrayNode #/baz> true]\n}\n", subject.pretty_inspect)
131
265
  end
132
266
  end
133
267
  end
@@ -137,43 +271,52 @@ describe JSI::BaseHash do
137
271
  it('#empty?') { assert_equal(false, subject.empty?) }
138
272
  it('#has_key?') { assert_equal(true, subject.has_key?('bar')) }
139
273
  it('#include?') { assert_equal(false, subject.include?('q')) }
140
- it('#key?') { assert_equal(true, subject.key?('baz')) }
141
- it('#keys') { assert_equal(['foo', 'bar', 'baz'], subject.keys) }
142
- it('#length') { assert_equal(3, subject.length) }
143
- it('#member?') { assert_equal(false, subject.member?(0)) }
144
- it('#size') { assert_equal(3, subject.size) }
274
+ it('#key?') { assert_equal(true, subject.key?('baz')) }
275
+ it('#keys') { assert_equal(['foo', 'bar', 'baz'], subject.keys) }
276
+ it('#length') { assert_equal(3, subject.length) }
277
+ it('#member?') { assert_equal(false, subject.member?(0)) }
278
+ it('#size') { assert_equal(3, subject.size) }
145
279
  end
146
280
  describe 'key + value methods' do
147
- it('#<') { assert_equal(true, subject < {'foo' => subject['foo'], 'bar' => subject['bar'], 'baz' => true, 'x' => 'y'}) } if {}.respond_to?(:<)
148
- it('#<=') { assert_equal(true, subject <= subject) } if {}.respond_to?(:<=)
149
- it('#>') { assert_equal(true, subject > {}) } if {}.respond_to?(:>)
150
- it('#>=') { assert_equal(false, subject >= {'foo' => 'bar'}) } if {}.respond_to?(:>=)
151
- it('#any?') { assert_equal(false, subject.any? { |k, v| v == 3 }) }
152
- it('#assoc') { assert_equal(['foo', subject['foo']], subject.assoc('foo')) }
153
- it('#dig') { assert_equal(9, subject.dig('bar', 0)) } if {}.respond_to?(:dig)
154
- it('#each_pair') { assert_equal([['foo', subject['foo']], ['bar', subject['bar']], ['baz', true]], subject.each_pair.to_a) }
155
- it('#each_value') { assert_equal([subject['foo'], subject['bar'], true], subject.each_value.to_a) }
156
- it('#fetch') { assert_equal(true, subject.fetch('baz')) }
157
- it('#fetch_values') { assert_equal([true], subject.fetch_values('baz')) } if {}.respond_to?(:fetch_values)
158
- it('#has_value?') { assert_equal(true, subject.has_value?(true)) }
159
- it('#invert') { assert_equal({subject['foo'] => 'foo', subject['bar'] => 'bar', true => 'baz'}, subject.invert) }
160
- it('#key') { assert_equal('baz', subject.key(true)) }
161
- it('#rassoc') { assert_equal(['baz', true], subject.rassoc(true)) }
162
- it('#to_h') { assert_equal({'foo' => subject['foo'], 'bar' => subject['bar'], 'baz' => true}, subject.to_h) }
163
- it('#to_proc') { assert_equal(true, subject.to_proc.call('baz')) } if {}.respond_to?(:to_proc)
281
+ it('#<') { assert_equal(true, subject < {'foo' => subject['foo'], 'bar' => subject['bar'], 'baz' => subject['baz'], 'x' => 'y'}) } if {}.respond_to?(:<)
282
+ it('#<=') { assert_equal(true, subject <= subject) } if {}.respond_to?(:<=)
283
+ it('#>') { assert_equal(true, subject > {}) } if {}.respond_to?(:>)
284
+ it('#>=') { assert_equal(false, subject >= {'foo' => 'bar'}) } if {}.respond_to?(:>=)
285
+ it('#any?') { assert_equal(false, subject.any? { |k, v| v == 3 }) }
286
+ it('#assoc') { assert_equal(['foo', subject['foo']], subject.assoc('foo')) }
287
+ it('#dig') { assert_equal(9, subject.dig('bar', 0)) } if {}.respond_to?(:dig)
288
+ it('#each_pair') { assert_equal([['foo', subject['foo']], ['bar', subject['bar']], ['baz', [true]]], subject.each_pair.to_a) }
289
+ it('#each_value') { assert_equal([subject['foo'], subject['bar'], [true]], subject.each_value.to_a) }
290
+ it('#fetch') { assert_equal([true], subject.fetch('baz')) }
291
+ it('#fetch_values') { assert_equal([[true]], subject.fetch_values('baz')) } if {}.respond_to?(:fetch_values)
292
+ it('#has_value?') { assert_equal(true, subject.has_value?([true])) }
293
+ it('#invert') { assert_equal({subject['foo'] => 'foo', subject['bar'] => 'bar', [true] => 'baz'}, subject.invert) }
294
+ it('#key') { assert_equal('baz', subject.key([true])) }
295
+ it('#rassoc') { assert_equal(['baz', [true]], subject.rassoc([true])) }
296
+ it('#to_h') { assert_equal({'foo' => subject['foo'], 'bar' => subject['bar'], 'baz' => [true]}, subject.to_h) }
297
+ it('#to_proc') { assert_equal([true], subject.to_proc.call('baz')) } if {}.respond_to?(:to_proc)
164
298
  if {}.respond_to?(:transform_values)
165
299
  it('#transform_values') { assert_equal({'foo' => nil, 'bar' => nil, 'baz' => nil}, subject.transform_values { |_| nil }) }
166
300
  end
167
- it('#value?') { assert_equal(false, subject.value?('0')) }
168
- it('#values') { assert_equal([subject['foo'], subject['bar'], true], subject.values) }
169
- it('#values_at') { assert_equal([true], subject.values_at('baz')) }
301
+ it('#value?') { assert_equal(false, subject.value?('0')) }
302
+ it('#values') { assert_equal([subject['foo'], subject['bar'], [true]], subject.values) }
303
+ it('#values_at') { assert_equal([[true]], subject.values_at('baz')) }
304
+ end
305
+ describe 'with an instance that has to_hash but not other hash instance methods' do
306
+ let(:instance) { SortOfHash.new({'foo' => SortOfHash.new({'a' => 'b'})}) }
307
+ describe 'delegating instance methods to #to_hash' do
308
+ it('#each_key') { assert_equal(['foo'], subject.each_key.to_a) }
309
+ it('#each_pair') { assert_equal([['foo', subject['foo']]], subject.each_pair.to_a) }
310
+ it('#[]') { assert_equal(SortOfHash.new({'a' => 'b'}), subject['foo'].jsi_instance) }
311
+ it('#as_json') { assert_equal({'foo' => {'a' => 'b'}}, subject.as_json) }
312
+ end
170
313
  end
171
314
  describe 'modified copy methods' do
172
315
  # I'm going to rely on the #merge test above to test the modified copy functionality and just do basic
173
316
  # tests of all the modified copy methods here
174
- it('#merge') { assert_equal(subject, subject.merge({})) }
175
- it('#reject') { assert_equal(class_for_schema.new(JSI::JSON::HashNode.new({}, [])), subject.reject { true }) }
176
- it('#select') { assert_equal(class_for_schema.new(JSI::JSON::HashNode.new({}, [])), subject.select { false }) }
317
+ it('#merge') { assert_equal(subject, subject.merge({})) }
318
+ it('#reject') { assert_equal(schema.new_jsi({}), subject.reject { true }) }
319
+ it('#select') { assert_equal(schema.new_jsi({}), subject.select { false }) }
177
320
  describe '#select' do
178
321
  it 'yields properly too' do
179
322
  subject.select do |k, v|