jsi 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +18 -15
- data/jsi.gemspec +1 -1
- data/lib/jsi.rb +5 -1
- data/lib/jsi/base.rb +222 -215
- data/lib/jsi/json-schema-fragments.rb +1 -1
- data/lib/jsi/json/node.rb +61 -146
- data/lib/jsi/json/pointer.rb +235 -41
- data/lib/jsi/pathed_node.rb +113 -0
- data/lib/jsi/schema.rb +46 -40
- data/lib/jsi/schema_classes.rb +86 -0
- data/lib/jsi/simple_wrap.rb +7 -0
- data/lib/jsi/typelike_modules.rb +39 -11
- data/lib/jsi/util.rb +3 -0
- data/lib/jsi/version.rb +1 -1
- data/test/base_array_test.rb +63 -51
- data/test/base_hash_test.rb +38 -28
- data/test/base_test.rb +54 -27
- data/test/jsi_json_arraynode_test.rb +19 -18
- data/test/jsi_json_hashnode_test.rb +29 -28
- data/test/jsi_json_node_test.rb +50 -28
- data/test/jsi_json_pointer_test.rb +13 -5
- data/test/schema_test.rb +13 -13
- data/test/spreedly_openapi_test.rb +8 -0
- data/test/test_helper.rb +3 -3
- data/test/util_test.rb +10 -10
- metadata +8 -3
data/lib/jsi/util.rb
CHANGED
data/lib/jsi/version.rb
CHANGED
data/test/base_array_test.rb
CHANGED
@@ -5,7 +5,8 @@ describe JSI::BaseArray do
|
|
5
5
|
['foo', {'lamp' => [3]}, ['q', 'r']]
|
6
6
|
end
|
7
7
|
let(:path) { [] }
|
8
|
-
let(:
|
8
|
+
let(:pointer) { JSI::JSON::Pointer.new(path) }
|
9
|
+
let(:instance) { JSI::JSON::Node.new_by_type(document, pointer) }
|
9
10
|
let(:schema_content) do
|
10
11
|
{
|
11
12
|
'type' => 'array',
|
@@ -106,40 +107,40 @@ describe JSI::BaseArray do
|
|
106
107
|
# these methods just delegate to Array so not going to test excessively
|
107
108
|
describe 'index only methods' do
|
108
109
|
it('#each_index') { assert_equal([0, 1, 2], subject.each_index.to_a) }
|
109
|
-
it('#empty?')
|
110
|
-
it('#length')
|
111
|
-
it('#size')
|
110
|
+
it('#empty?') { assert_equal(false, subject.empty?) }
|
111
|
+
it('#length') { assert_equal(3, subject.length) }
|
112
|
+
it('#size') { assert_equal(3, subject.size) }
|
112
113
|
end
|
113
114
|
describe 'index + element methods' do
|
114
|
-
it('#|')
|
115
|
-
it('#&')
|
116
|
-
it('#*')
|
117
|
-
it('#+')
|
118
|
-
it('#-')
|
119
|
-
it('#<=>')
|
120
|
-
it('#<=>')
|
115
|
+
it('#|') { assert_equal(['foo', subject[1], subject[2], 0], subject | [0]) }
|
116
|
+
it('#&') { assert_equal(['foo'], subject & ['foo']) }
|
117
|
+
it('#*') { assert_equal(subject.to_a, subject * 1) }
|
118
|
+
it('#+') { assert_equal(subject.to_a, subject + []) }
|
119
|
+
it('#-') { assert_equal([subject[1], subject[2]], subject - ['foo']) }
|
120
|
+
it('#<=>') { assert_equal(1, subject <=> []) }
|
121
|
+
it('#<=>') { assert_equal(-1, [] <=> subject) }
|
121
122
|
require 'abbrev'
|
122
|
-
it('#abbrev')
|
123
|
-
it('#assoc')
|
124
|
-
it('#at')
|
125
|
-
it('#bsearch')
|
126
|
-
it('#bsearch_index')
|
127
|
-
it('#combination')
|
128
|
-
it('#count')
|
129
|
-
it('#cycle')
|
130
|
-
it('#dig')
|
131
|
-
it('#drop')
|
132
|
-
it('#drop_while')
|
133
|
-
it('#fetch')
|
134
|
-
it('#find_index')
|
135
|
-
it('#first')
|
136
|
-
it('#include?')
|
137
|
-
it('#index')
|
138
|
-
it('#join')
|
139
|
-
it('#last')
|
140
|
-
it('#pack')
|
141
|
-
it('#permutation')
|
142
|
-
it('#product')
|
123
|
+
it('#abbrev') { assert_equal({'a' => 'a'}, class_for_schema.new(['a']).abbrev) }
|
124
|
+
it('#assoc') { assert_equal(['q', 'r'], subject.assoc('q')) }
|
125
|
+
it('#at') { assert_equal('foo', subject.at(0)) }
|
126
|
+
it('#bsearch') { assert_equal(nil, subject.bsearch { false }) }
|
127
|
+
it('#bsearch_index') { assert_equal(nil, subject.bsearch_index { false }) } if [].respond_to?(:bsearch_index)
|
128
|
+
it('#combination') { assert_equal([['foo'], [subject[1]], [subject[2]]], subject.combination(1).to_a) }
|
129
|
+
it('#count') { assert_equal(1, subject.count('foo')) }
|
130
|
+
it('#cycle') { assert_equal(subject.to_a, subject.cycle(1).to_a) }
|
131
|
+
it('#dig') { assert_equal(3, subject.dig(1, 'lamp', 0)) } if [].respond_to?(:dig)
|
132
|
+
it('#drop') { assert_equal([subject[2]], subject.drop(2)) }
|
133
|
+
it('#drop_while') { assert_equal([subject[1], subject[2]], subject.drop_while { |e| e == 'foo' }) }
|
134
|
+
it('#fetch') { assert_equal('foo', subject.fetch(0)) }
|
135
|
+
it('#find_index') { assert_equal(0, subject.find_index { true }) }
|
136
|
+
it('#first') { assert_equal('foo', subject.first) }
|
137
|
+
it('#include?') { assert_equal(true, subject.include?('foo')) }
|
138
|
+
it('#index') { assert_equal(0, subject.index('foo')) }
|
139
|
+
it('#join') { assert_equal('a b', class_for_schema.new(['a', 'b']).join(' ')) }
|
140
|
+
it('#last') { assert_equal(subject[2], subject.last) }
|
141
|
+
it('#pack') { assert_equal(' ', class_for_schema.new([32]).pack('c')) }
|
142
|
+
it('#permutation') { assert_equal([['foo'], [subject[1]], [subject[2]]], subject.permutation(1).to_a) }
|
143
|
+
it('#product') { assert_equal([], subject.product([])) }
|
143
144
|
# due to differences in implementation between #assoc and #rassoc, the reason for which
|
144
145
|
# I cannot begin to fathom, assoc works but rassoc does not because rassoc has different
|
145
146
|
# type checking than assoc for the array(like) array elements.
|
@@ -147,32 +148,43 @@ describe JSI::BaseArray do
|
|
147
148
|
# assoc: https://github.com/ruby/ruby/blob/v2_5_0/array.c#L3780-L3813
|
148
149
|
# rassoc: https://github.com/ruby/ruby/blob/v2_5_0/array.c#L3815-L3847
|
149
150
|
# for this reason, rassoc is NOT defined on Arraylike and #content must be called.
|
150
|
-
it('#rassoc')
|
151
|
+
it('#rassoc') { assert_equal(['q', 'r'], subject.instance.content.rassoc('r')) }
|
151
152
|
it('#repeated_combination') { assert_equal([[]], subject.repeated_combination(0).to_a) }
|
152
153
|
it('#repeated_permutation') { assert_equal([[]], subject.repeated_permutation(0).to_a) }
|
153
|
-
it('#reverse')
|
154
|
-
it('#reverse_each')
|
155
|
-
it('#rindex')
|
156
|
-
it('#rotate')
|
157
|
-
it('#sample')
|
158
|
-
it('#shelljoin')
|
159
|
-
it('#shuffle')
|
160
|
-
it('#slice')
|
161
|
-
it('#sort')
|
162
|
-
it('#take')
|
163
|
-
it('#take_while')
|
164
|
-
it('#transpose')
|
165
|
-
it('#uniq')
|
166
|
-
it('#values_at')
|
167
|
-
it('#zip')
|
154
|
+
it('#reverse') { assert_equal([subject[2], subject[1], 'foo'], subject.reverse) }
|
155
|
+
it('#reverse_each') { assert_equal([subject[2], subject[1], 'foo'], subject.reverse_each.to_a) }
|
156
|
+
it('#rindex') { assert_equal(0, subject.rindex('foo')) }
|
157
|
+
it('#rotate') { assert_equal([subject[1], subject[2], 'foo'], subject.rotate) }
|
158
|
+
it('#sample') { assert_equal('a', class_for_schema.new(['a']).sample) }
|
159
|
+
it('#shelljoin') { assert_equal('a', class_for_schema.new(['a']).shelljoin) } if [].respond_to?(:shelljoin)
|
160
|
+
it('#shuffle') { assert_equal(3, subject.shuffle.size) }
|
161
|
+
it('#slice') { assert_equal(['foo'], subject.slice(0, 1)) }
|
162
|
+
it('#sort') { assert_equal(['a'], class_for_schema.new(['a']).sort) }
|
163
|
+
it('#take') { assert_equal(['foo'], subject.take(1)) }
|
164
|
+
it('#take_while') { assert_equal([], subject.take_while { false }) }
|
165
|
+
it('#transpose') { assert_equal([], class_for_schema.new([]).transpose) }
|
166
|
+
it('#uniq') { assert_equal(subject.to_a, subject.uniq) }
|
167
|
+
it('#values_at') { assert_equal(['foo'], subject.values_at(0)) }
|
168
|
+
it('#zip') { assert_equal([['foo', 'foo'], [subject[1], subject[1]], [subject[2], subject[2]]], subject.zip(subject)) }
|
169
|
+
end
|
170
|
+
describe 'with an instance that has to_ary but not other ary instance methods' do
|
171
|
+
let(:instance) { SortOfArray.new(['foo', {'lamp' => SortOfArray.new([3])}, SortOfArray.new(['q', 'r'])]) }
|
172
|
+
describe 'delegating instance methods to #to_ary' do
|
173
|
+
it('#each_index') { assert_equal([0, 1, 2], subject.each_index.to_a) }
|
174
|
+
it('#size') { assert_equal(3, subject.size) }
|
175
|
+
it('#count') { assert_equal(1, subject.count('foo')) }
|
176
|
+
it('#slice') { assert_equal(['foo'], subject.slice(0, 1)) }
|
177
|
+
it('#[]') { assert_equal(SortOfArray.new(['q', 'r']), subject[2].instance) }
|
178
|
+
it('#as_json') { assert_equal(['foo', {'lamp' => [3]}, ['q', 'r']], subject.as_json) }
|
179
|
+
end
|
168
180
|
end
|
169
181
|
describe 'modified copy methods' do
|
170
|
-
it('#reject') { assert_equal(class_for_schema.new(JSI::JSON::ArrayNode.new(['foo'],
|
182
|
+
it('#reject') { assert_equal(class_for_schema.new(JSI::JSON::ArrayNode.new(['foo'], pointer)), subject.reject { |e| e != 'foo' }) }
|
171
183
|
it('#reject block var') do
|
172
184
|
subj_a = subject.to_a
|
173
185
|
subject.reject { |e| assert_equal(e, subj_a.shift) }
|
174
186
|
end
|
175
|
-
it('#select') { assert_equal(class_for_schema.new(JSI::JSON::ArrayNode.new(['foo'],
|
187
|
+
it('#select') { assert_equal(class_for_schema.new(JSI::JSON::ArrayNode.new(['foo'], pointer)), subject.select { |e| e == 'foo' }) }
|
176
188
|
it('#select block var') do
|
177
189
|
subj_a = subject.to_a
|
178
190
|
subject.select { |e| assert_equal(e, subj_a.shift) }
|
@@ -183,7 +195,7 @@ describe JSI::BaseArray do
|
|
183
195
|
let(:path) { ['1', 'c'] }
|
184
196
|
it('#select') do
|
185
197
|
selected = subject.select { |e| e == 'd' }
|
186
|
-
equivalent_node = JSI::JSON::ArrayNode.new([['b', 'q'], {'c' => ['d']}],
|
198
|
+
equivalent_node = JSI::JSON::ArrayNode.new([['b', 'q'], {'c' => ['d']}], pointer)
|
187
199
|
equivalent = class_for_schema.new(equivalent_node)
|
188
200
|
assert_equal(equivalent, selected)
|
189
201
|
end
|
data/test/base_hash_test.rb
CHANGED
@@ -5,7 +5,8 @@ describe JSI::BaseHash do
|
|
5
5
|
{'foo' => {'x' => 'y'}, 'bar' => [9], 'baz' => true}
|
6
6
|
end
|
7
7
|
let(:path) { [] }
|
8
|
-
let(:
|
8
|
+
let(:pointer) { JSI::JSON::Pointer.new(path) }
|
9
|
+
let(:instance) { JSI::JSON::Node.new_by_type(document, pointer) }
|
9
10
|
let(:schema_content) do
|
10
11
|
{
|
11
12
|
'type' => 'object',
|
@@ -137,43 +138,52 @@ describe JSI::BaseHash do
|
|
137
138
|
it('#empty?') { assert_equal(false, subject.empty?) }
|
138
139
|
it('#has_key?') { assert_equal(true, subject.has_key?('bar')) }
|
139
140
|
it('#include?') { assert_equal(false, subject.include?('q')) }
|
140
|
-
it('#key?')
|
141
|
-
it('#keys')
|
142
|
-
it('#length')
|
143
|
-
it('#member?')
|
144
|
-
it('#size')
|
141
|
+
it('#key?') { assert_equal(true, subject.key?('baz')) }
|
142
|
+
it('#keys') { assert_equal(['foo', 'bar', 'baz'], subject.keys) }
|
143
|
+
it('#length') { assert_equal(3, subject.length) }
|
144
|
+
it('#member?') { assert_equal(false, subject.member?(0)) }
|
145
|
+
it('#size') { assert_equal(3, subject.size) }
|
145
146
|
end
|
146
147
|
describe 'key + value methods' do
|
147
|
-
it('#<')
|
148
|
-
it('#<=')
|
149
|
-
it('#>')
|
150
|
-
it('#>=')
|
151
|
-
it('#any?')
|
152
|
-
it('#assoc')
|
153
|
-
it('#dig')
|
154
|
-
it('#each_pair')
|
155
|
-
it('#each_value')
|
156
|
-
it('#fetch')
|
148
|
+
it('#<') { assert_equal(true, subject < {'foo' => subject['foo'], 'bar' => subject['bar'], 'baz' => true, 'x' => 'y'}) } if {}.respond_to?(:<)
|
149
|
+
it('#<=') { assert_equal(true, subject <= subject) } if {}.respond_to?(:<=)
|
150
|
+
it('#>') { assert_equal(true, subject > {}) } if {}.respond_to?(:>)
|
151
|
+
it('#>=') { assert_equal(false, subject >= {'foo' => 'bar'}) } if {}.respond_to?(:>=)
|
152
|
+
it('#any?') { assert_equal(false, subject.any? { |k, v| v == 3 }) }
|
153
|
+
it('#assoc') { assert_equal(['foo', subject['foo']], subject.assoc('foo')) }
|
154
|
+
it('#dig') { assert_equal(9, subject.dig('bar', 0)) } if {}.respond_to?(:dig)
|
155
|
+
it('#each_pair') { assert_equal([['foo', subject['foo']], ['bar', subject['bar']], ['baz', true]], subject.each_pair.to_a) }
|
156
|
+
it('#each_value') { assert_equal([subject['foo'], subject['bar'], true], subject.each_value.to_a) }
|
157
|
+
it('#fetch') { assert_equal(true, subject.fetch('baz')) }
|
157
158
|
it('#fetch_values') { assert_equal([true], subject.fetch_values('baz')) } if {}.respond_to?(:fetch_values)
|
158
|
-
it('#has_value?')
|
159
|
-
it('#invert')
|
160
|
-
it('#key')
|
161
|
-
it('#rassoc')
|
162
|
-
it('#to_h')
|
163
|
-
it('#to_proc')
|
159
|
+
it('#has_value?') { assert_equal(true, subject.has_value?(true)) }
|
160
|
+
it('#invert') { assert_equal({subject['foo'] => 'foo', subject['bar'] => 'bar', true => 'baz'}, subject.invert) }
|
161
|
+
it('#key') { assert_equal('baz', subject.key(true)) }
|
162
|
+
it('#rassoc') { assert_equal(['baz', true], subject.rassoc(true)) }
|
163
|
+
it('#to_h') { assert_equal({'foo' => subject['foo'], 'bar' => subject['bar'], 'baz' => true}, subject.to_h) }
|
164
|
+
it('#to_proc') { assert_equal(true, subject.to_proc.call('baz')) } if {}.respond_to?(:to_proc)
|
164
165
|
if {}.respond_to?(:transform_values)
|
165
166
|
it('#transform_values') { assert_equal({'foo' => nil, 'bar' => nil, 'baz' => nil}, subject.transform_values { |_| nil }) }
|
166
167
|
end
|
167
|
-
it('#value?')
|
168
|
-
it('#values')
|
169
|
-
it('#values_at')
|
168
|
+
it('#value?') { assert_equal(false, subject.value?('0')) }
|
169
|
+
it('#values') { assert_equal([subject['foo'], subject['bar'], true], subject.values) }
|
170
|
+
it('#values_at') { assert_equal([true], subject.values_at('baz')) }
|
171
|
+
end
|
172
|
+
describe 'with an instance that has to_hash but not other hash instance methods' do
|
173
|
+
let(:instance) { SortOfHash.new({'foo' => SortOfHash.new({'a' => 'b'})}) }
|
174
|
+
describe 'delegating instance methods to #to_hash' do
|
175
|
+
it('#each_key') { assert_equal(['foo'], subject.each_key.to_a) }
|
176
|
+
it('#each_pair') { assert_equal([['foo', subject['foo']]], subject.each_pair.to_a) }
|
177
|
+
it('#[]') { assert_equal(SortOfHash.new({'a' => 'b'}), subject['foo'].instance) }
|
178
|
+
it('#as_json') { assert_equal({'foo' => {'a' => 'b'}}, subject.as_json) }
|
179
|
+
end
|
170
180
|
end
|
171
181
|
describe 'modified copy methods' do
|
172
182
|
# I'm going to rely on the #merge test above to test the modified copy functionality and just do basic
|
173
183
|
# tests of all the modified copy methods here
|
174
|
-
it('#merge')
|
175
|
-
it('#reject') { assert_equal(class_for_schema.new(JSI::JSON::HashNode.new({},
|
176
|
-
it('#select') { assert_equal(class_for_schema.new(JSI::JSON::HashNode.new({},
|
184
|
+
it('#merge') { assert_equal(subject, subject.merge({})) }
|
185
|
+
it('#reject') { assert_equal(class_for_schema.new(JSI::JSON::HashNode.new({}, pointer)), subject.reject { true }) }
|
186
|
+
it('#select') { assert_equal(class_for_schema.new(JSI::JSON::HashNode.new({}, pointer)), subject.select { false }) }
|
177
187
|
describe '#select' do
|
178
188
|
it 'yields properly too' do
|
179
189
|
subject.select do |k, v|
|
data/test/base_test.rb
CHANGED
@@ -5,7 +5,8 @@ NamedSchemaInstance = JSI.class_for_schema({id: 'https://schemas.jsi.unth.net/te
|
|
5
5
|
describe JSI::Base do
|
6
6
|
let(:document) { {} }
|
7
7
|
let(:path) { [] }
|
8
|
-
let(:
|
8
|
+
let(:pointer) { JSI::JSON::Pointer.new(path) }
|
9
|
+
let(:instance) { JSI::JSON::Node.new_by_type(document, pointer) }
|
9
10
|
let(:schema_content) { {} }
|
10
11
|
let(:schema) { JSI::Schema.new(schema_content) }
|
11
12
|
let(:subject) { JSI.class_for_schema(schema).new(instance) }
|
@@ -107,7 +108,7 @@ describe JSI::Base do
|
|
107
108
|
describe 'nil' do
|
108
109
|
let(:instance) { nil }
|
109
110
|
it 'initializes with nil instance' do
|
110
|
-
assert_equal(
|
111
|
+
assert_equal(nil, subject.instance)
|
111
112
|
assert(!subject.respond_to?(:to_ary))
|
112
113
|
assert(!subject.respond_to?(:to_hash))
|
113
114
|
end
|
@@ -115,7 +116,7 @@ describe JSI::Base do
|
|
115
116
|
describe 'arbitrary instance' do
|
116
117
|
let(:instance) { Object.new }
|
117
118
|
it 'initializes' do
|
118
|
-
assert_equal(
|
119
|
+
assert_equal(instance, subject.instance)
|
119
120
|
assert(!subject.respond_to?(:to_ary))
|
120
121
|
assert(!subject.respond_to?(:to_hash))
|
121
122
|
end
|
@@ -124,7 +125,7 @@ describe JSI::Base do
|
|
124
125
|
let(:instance) { {'foo' => 'bar'} }
|
125
126
|
let(:schema_content) { {'type' => 'object'} }
|
126
127
|
it 'initializes' do
|
127
|
-
assert_equal(
|
128
|
+
assert_equal({'foo' => 'bar'}, subject.instance)
|
128
129
|
assert(!subject.respond_to?(:to_ary))
|
129
130
|
assert(subject.respond_to?(:to_hash))
|
130
131
|
end
|
@@ -133,7 +134,7 @@ describe JSI::Base do
|
|
133
134
|
let(:document) { {'foo' => 'bar'} }
|
134
135
|
let(:schema_content) { {'type' => 'object'} }
|
135
136
|
it 'initializes' do
|
136
|
-
assert_equal(JSI::JSON::HashNode.new({'foo' => 'bar'}, []), subject.instance)
|
137
|
+
assert_equal(JSI::JSON::HashNode.new({'foo' => 'bar'}, JSI::JSON::Pointer.new([])), subject.instance)
|
137
138
|
assert(!subject.respond_to?(:to_ary))
|
138
139
|
assert(subject.respond_to?(:to_hash))
|
139
140
|
end
|
@@ -142,7 +143,7 @@ describe JSI::Base do
|
|
142
143
|
let(:instance) { ['foo'] }
|
143
144
|
let(:schema_content) { {'type' => 'array'} }
|
144
145
|
it 'initializes' do
|
145
|
-
assert_equal(
|
146
|
+
assert_equal(['foo'], subject.instance)
|
146
147
|
assert(subject.respond_to?(:to_ary))
|
147
148
|
assert(!subject.respond_to?(:to_hash))
|
148
149
|
end
|
@@ -151,41 +152,52 @@ describe JSI::Base do
|
|
151
152
|
let(:document) { ['foo'] }
|
152
153
|
let(:schema_content) { {'type' => 'array'} }
|
153
154
|
it 'initializes' do
|
154
|
-
assert_equal(JSI::JSON::ArrayNode.new(['foo'], []), subject.instance)
|
155
|
+
assert_equal(JSI::JSON::ArrayNode.new(['foo'], JSI::JSON::Pointer.new([])), subject.instance)
|
155
156
|
assert(subject.respond_to?(:to_ary))
|
156
157
|
assert(!subject.respond_to?(:to_hash))
|
157
158
|
end
|
158
159
|
end
|
159
|
-
describe 'another Base' do
|
160
|
+
describe 'another JSI::Base invalid' do
|
160
161
|
let(:schema_content) { {'type' => 'object'} }
|
161
162
|
let(:instance) { JSI.class_for_schema(schema).new({'foo' => 'bar'}) }
|
162
|
-
it 'initializes with
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
163
|
+
it 'initializes with an error' do
|
164
|
+
err = assert_raises(TypeError) { subject }
|
165
|
+
assert_match(%r(\Aassigning another JSI::Base instance to JSI::SchemaClasses\[\".*#\"\] instance is incorrect. received: #\{<JSI::SchemaClasses\[.*\] Hash>\s*"foo" => "bar"\s*\}\z)m, err.message)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
describe 'Schema invalid' do
|
169
|
+
let(:instance) { JSI::Schema.new({}) }
|
170
|
+
it 'initializes with an error' do
|
171
|
+
err = assert_raises(TypeError) { subject }
|
172
|
+
assert_match(%r(\Aassigning a schema to JSI::SchemaClasses\[\".*#\"\] instance is incorrect. received: #<JSI::Schema schema_id=.*>\z)m, err.message)
|
167
173
|
end
|
168
174
|
end
|
169
175
|
end
|
170
|
-
describe '#
|
176
|
+
describe '#parent_jsis, #parent_jsi' do
|
171
177
|
let(:schema_content) { {'properties' => {'foo' => {'properties' => {'bar' => {'properties' => {'baz' => {}}}}}}} }
|
172
178
|
let(:document) { {'foo' => {'bar' => {'baz' => {}}}} }
|
173
|
-
describe 'no
|
179
|
+
describe 'no parent_jsis' do
|
174
180
|
it 'has none' do
|
175
181
|
assert_equal([], subject.parents)
|
182
|
+
assert_equal([], subject.parent_jsis.to_a)
|
176
183
|
assert_equal(nil, subject.parent)
|
184
|
+
assert_equal(nil, subject.parent_jsi)
|
177
185
|
end
|
178
186
|
end
|
179
|
-
describe 'one
|
187
|
+
describe 'one parent_jsi' do
|
180
188
|
it 'has one' do
|
181
189
|
assert_equal([subject], subject.foo.parents)
|
190
|
+
assert_equal([subject], subject.foo.parent_jsis.to_a)
|
182
191
|
assert_equal(subject, subject.foo.parent)
|
192
|
+
assert_equal(subject, subject.foo.parent_jsi)
|
183
193
|
end
|
184
194
|
end
|
185
|
-
describe 'more
|
195
|
+
describe 'more parent_jsis' do
|
186
196
|
it 'has more' do
|
187
197
|
assert_equal([subject.foo.bar, subject.foo, subject], subject.foo.bar.baz.parents)
|
198
|
+
assert_equal([subject.foo.bar, subject.foo, subject], subject.foo.bar.baz.parent_jsis.to_a)
|
188
199
|
assert_equal(subject.foo.bar, subject.foo.bar.baz.parent)
|
200
|
+
assert_equal(subject.foo.bar, subject.foo.bar.baz.parent_jsi)
|
189
201
|
end
|
190
202
|
end
|
191
203
|
end
|
@@ -197,6 +209,19 @@ describe JSI::Base do
|
|
197
209
|
end
|
198
210
|
end
|
199
211
|
describe '#modified_copy' do
|
212
|
+
describe 'with an instance that does not have #modified_copy' do
|
213
|
+
let(:instance) { Object.new }
|
214
|
+
it 'yields the instance to modify' do
|
215
|
+
new_instance = Object.new
|
216
|
+
modified = subject.modified_copy do |o|
|
217
|
+
assert_equal(instance, o)
|
218
|
+
new_instance
|
219
|
+
end
|
220
|
+
assert_equal(new_instance, modified.instance)
|
221
|
+
assert_equal(instance, subject.instance)
|
222
|
+
refute_equal(instance, modified)
|
223
|
+
end
|
224
|
+
end
|
200
225
|
describe 'with an instance that does have #modified_copy' do
|
201
226
|
it 'yields the instance to modify' do
|
202
227
|
modified = subject.modified_copy do |o|
|
@@ -282,7 +307,7 @@ describe JSI::Base do
|
|
282
307
|
let(:instance) { nil }
|
283
308
|
it 'errors' do
|
284
309
|
err = assert_raises(NoMethodError) { subject.foo }
|
285
|
-
assert_match(%r(\
|
310
|
+
assert_match(%r(\Aschema instance of class .* does not respond to \[\]; cannot call reader 'foo'. instance is )m, err.message)
|
286
311
|
end
|
287
312
|
end
|
288
313
|
describe 'properties with the same names as instance methods' do
|
@@ -317,7 +342,7 @@ describe JSI::Base do
|
|
317
342
|
end
|
318
343
|
it 'does not define readers' do
|
319
344
|
assert_equal('bar', subject.foo)
|
320
|
-
assert_equal(JSI::SchemaClasses.module_for_schema(subject.schema), subject.method(:foo).owner)
|
345
|
+
assert_equal(JSI::SchemaClasses.module_for_schema(subject.schema, conflicting_modules: [JSI::Base, JSI::BaseArray, JSI::BaseHash]), subject.method(:foo).owner)
|
321
346
|
|
322
347
|
assert_equal(JSI::Base, subject.method(:initialize).owner)
|
323
348
|
assert_equal('hi', subject['initialize'])
|
@@ -356,7 +381,7 @@ describe JSI::Base do
|
|
356
381
|
let(:instance) { nil }
|
357
382
|
it 'errors' do
|
358
383
|
err = assert_raises(NoMethodError) { subject.foo = 0 }
|
359
|
-
assert_match(%r(\
|
384
|
+
assert_match(%r(\Aschema instance of class .* does not respond to \[\]=; cannot call writer 'foo='. instance is )m, err.message)
|
360
385
|
end
|
361
386
|
end
|
362
387
|
end
|
@@ -383,13 +408,15 @@ describe JSI::Base do
|
|
383
408
|
assert_equal(['a'], JSI.class_for_schema({}).new(['a']).as_json(some_option: true))
|
384
409
|
end
|
385
410
|
end
|
386
|
-
describe '
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
411
|
+
describe 'equality between different classes of JSI::Base subclasses' do
|
412
|
+
let(:subject_subclass) { Class.new(JSI.class_for_schema(schema)).new(instance) }
|
413
|
+
|
414
|
+
it 'considers a Base subclass (class_for_schema) and subsubclass to be equal with the same instance' do
|
415
|
+
assert_equal(subject.hash, subject_subclass.hash)
|
416
|
+
assert(subject == subject_subclass)
|
417
|
+
assert(subject_subclass == subject)
|
418
|
+
assert(subject.eql?(subject_subclass))
|
419
|
+
assert(subject_subclass.eql?(subject))
|
393
420
|
end
|
394
421
|
end
|
395
422
|
end
|
@@ -18,8 +18,9 @@ document_types.each do |document_type|
|
|
18
18
|
let(:document) { document_type[:document] }
|
19
19
|
# by default the node is the whole document
|
20
20
|
let(:path) { [] }
|
21
|
+
let(:pointer) { JSI::JSON::Pointer.new(path) }
|
21
22
|
# the node being tested
|
22
|
-
let(:node) { JSI::JSON::Node.new_by_type(document,
|
23
|
+
let(:node) { JSI::JSON::Node.new_by_type(document, pointer) }
|
23
24
|
|
24
25
|
describe '#[] bad index' do
|
25
26
|
it 'improves TypeError for Array subsript' do
|
@@ -107,24 +108,24 @@ document_types.each do |document_type|
|
|
107
108
|
# for this reason, rassoc is NOT defined on Arraylike. it's here with as_json.
|
108
109
|
#
|
109
110
|
# I've never even seen anybody use rassoc. of all the methods to put into the standard library ...
|
110
|
-
it('#rassoc')
|
111
|
+
it('#rassoc') { assert_equal(['b', 'q'], node.as_json.rassoc('q')) }
|
111
112
|
it('#repeated_combination') { assert_equal([[]], node.repeated_combination(0).to_a) }
|
112
113
|
it('#repeated_permutation') { assert_equal([[]], node.repeated_permutation(0).to_a) }
|
113
|
-
it('#reverse')
|
114
|
-
it('#reverse_each')
|
115
|
-
it('#rindex')
|
116
|
-
it('#rotate')
|
117
|
-
it('#sample')
|
118
|
-
it('#shelljoin')
|
119
|
-
it('#shuffle')
|
120
|
-
it('#slice')
|
121
|
-
it('#sort')
|
122
|
-
it('#take')
|
123
|
-
it('#take_while')
|
124
|
-
it('#transpose')
|
125
|
-
it('#uniq')
|
126
|
-
it('#values_at')
|
127
|
-
it('#zip')
|
114
|
+
it('#reverse') { assert_equal([node[2], node[1], 'a'], node.reverse) }
|
115
|
+
it('#reverse_each') { assert_equal([node[2], node[1], 'a'], node.reverse_each.to_a) }
|
116
|
+
it('#rindex') { assert_equal(0, node.rindex('a')) }
|
117
|
+
it('#rotate') { assert_equal([node[1], node[2], 'a'], node.rotate) }
|
118
|
+
it('#sample') { assert_equal('a', JSI::JSON::Node.new_doc(['a']).sample) }
|
119
|
+
it('#shelljoin') { assert_equal('a', JSI::JSON::Node.new_doc(['a']).shelljoin) } if [].respond_to?(:shelljoin)
|
120
|
+
it('#shuffle') { assert_equal(3, node.shuffle.size) }
|
121
|
+
it('#slice') { assert_equal(['a'], node.slice(0, 1)) }
|
122
|
+
it('#sort') { assert_equal(['a'], JSI::JSON::Node.new_doc(['a']).sort) }
|
123
|
+
it('#take') { assert_equal(['a'], node.take(1)) }
|
124
|
+
it('#take_while') { assert_equal([], node.take_while { false }) }
|
125
|
+
it('#transpose') { assert_equal([], JSI::JSON::Node.new_doc([]).transpose) }
|
126
|
+
it('#uniq') { assert_equal(node.to_a, node.uniq) }
|
127
|
+
it('#values_at') { assert_equal(['a'], node.values_at(0)) }
|
128
|
+
it('#zip') { assert_equal([['a', 'a'], [node[1], node[1]], [node[2], node[2]]], node.zip(node)) }
|
128
129
|
end
|
129
130
|
describe 'modified copy methods' do
|
130
131
|
it('#reject') { assert_equal(JSI::JSON::Node.new_doc(['a']), node.reject { |e| e != 'a' }) }
|
@@ -135,7 +136,7 @@ document_types.each do |document_type|
|
|
135
136
|
let(:path) { ['1', 'c'] }
|
136
137
|
it('#select') do
|
137
138
|
selected = node.select { |e| e == 'd' }
|
138
|
-
equivalent = JSI::JSON::Node.new_by_type([['b', 'q'], {'c' => ['d']}],
|
139
|
+
equivalent = JSI::JSON::Node.new_by_type([['b', 'q'], {'c' => ['d']}], pointer)
|
139
140
|
assert_equal(equivalent, selected)
|
140
141
|
end
|
141
142
|
end
|