jsi 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|