jsi 0.4.0 → 0.7.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/.yardopts +1 -1
- data/CHANGELOG.md +33 -0
- data/LICENSE.md +1 -1
- data/README.md +114 -42
- data/jsi.gemspec +14 -12
- data/lib/jsi/base/node.rb +183 -0
- data/lib/jsi/base.rb +388 -220
- data/lib/jsi/jsi_coder.rb +8 -7
- data/lib/jsi/metaschema.rb +0 -1
- data/lib/jsi/metaschema_node/bootstrap_schema.rb +101 -0
- data/lib/jsi/metaschema_node.rb +159 -135
- data/lib/jsi/ptr.rb +303 -0
- data/lib/jsi/schema/application/child_application/contains.rb +25 -0
- data/lib/jsi/schema/application/child_application/draft04.rb +22 -0
- data/lib/jsi/schema/application/child_application/draft06.rb +29 -0
- data/lib/jsi/schema/application/child_application/draft07.rb +29 -0
- data/lib/jsi/schema/application/child_application/items.rb +18 -0
- data/lib/jsi/schema/application/child_application/properties.rb +25 -0
- data/lib/jsi/schema/application/child_application.rb +38 -0
- data/lib/jsi/schema/application/draft04.rb +8 -0
- data/lib/jsi/schema/application/draft06.rb +8 -0
- data/lib/jsi/schema/application/draft07.rb +8 -0
- data/lib/jsi/schema/application/inplace_application/dependencies.rb +28 -0
- data/lib/jsi/schema/application/inplace_application/draft04.rb +26 -0
- data/lib/jsi/schema/application/inplace_application/draft06.rb +27 -0
- data/lib/jsi/schema/application/inplace_application/draft07.rb +33 -0
- data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +20 -0
- data/lib/jsi/schema/application/inplace_application/ref.rb +18 -0
- data/lib/jsi/schema/application/inplace_application/someof.rb +44 -0
- data/lib/jsi/schema/application/inplace_application.rb +41 -0
- data/lib/jsi/schema/application.rb +12 -0
- data/lib/jsi/schema/draft04.rb +14 -0
- data/lib/jsi/schema/draft06.rb +14 -0
- data/lib/jsi/schema/draft07.rb +14 -0
- data/lib/jsi/schema/issue.rb +36 -0
- data/lib/jsi/schema/ref.rb +160 -0
- data/lib/jsi/schema/schema_ancestor_node.rb +113 -0
- data/lib/jsi/schema/validation/array.rb +69 -0
- data/lib/jsi/schema/validation/const.rb +20 -0
- data/lib/jsi/schema/validation/contains.rb +25 -0
- data/lib/jsi/schema/validation/core.rb +39 -0
- data/lib/jsi/schema/validation/dependencies.rb +49 -0
- data/lib/jsi/schema/validation/draft04/minmax.rb +91 -0
- data/lib/jsi/schema/validation/draft04.rb +112 -0
- data/lib/jsi/schema/validation/draft06.rb +122 -0
- data/lib/jsi/schema/validation/draft07.rb +159 -0
- data/lib/jsi/schema/validation/enum.rb +25 -0
- data/lib/jsi/schema/validation/ifthenelse.rb +46 -0
- data/lib/jsi/schema/validation/items.rb +54 -0
- data/lib/jsi/schema/validation/not.rb +20 -0
- data/lib/jsi/schema/validation/numeric.rb +121 -0
- data/lib/jsi/schema/validation/object.rb +45 -0
- data/lib/jsi/schema/validation/pattern.rb +34 -0
- data/lib/jsi/schema/validation/properties.rb +101 -0
- data/lib/jsi/schema/validation/property_names.rb +32 -0
- data/lib/jsi/schema/validation/ref.rb +40 -0
- data/lib/jsi/schema/validation/required.rb +27 -0
- data/lib/jsi/schema/validation/someof.rb +90 -0
- data/lib/jsi/schema/validation/string.rb +47 -0
- data/lib/jsi/schema/validation/type.rb +49 -0
- data/lib/jsi/schema/validation.rb +51 -0
- data/lib/jsi/schema.rb +508 -149
- data/lib/jsi/schema_classes.rb +199 -59
- data/lib/jsi/schema_registry.rb +151 -0
- data/lib/jsi/schema_set.rb +181 -0
- data/lib/jsi/simple_wrap.rb +23 -4
- data/lib/jsi/util/private/attr_struct.rb +127 -0
- data/lib/jsi/util/private.rb +204 -0
- data/lib/jsi/util/typelike.rb +229 -0
- data/lib/jsi/util.rb +89 -53
- data/lib/jsi/validation/error.rb +34 -0
- data/lib/jsi/validation/result.rb +210 -0
- data/lib/jsi/validation.rb +15 -0
- data/lib/jsi/version.rb +3 -1
- data/lib/jsi.rb +44 -14
- data/lib/schemas/json-schema.org/draft-04/schema.rb +10 -3
- data/lib/schemas/json-schema.org/draft-06/schema.rb +10 -3
- data/lib/schemas/json-schema.org/draft-07/schema.rb +14 -0
- data/readme.rb +138 -0
- data/{resources}/schemas/json-schema.org/draft-04/schema.json +149 -0
- data/{resources}/schemas/json-schema.org/draft-06/schema.json +154 -0
- data/{resources}/schemas/json-schema.org/draft-07/schema.json +168 -0
- metadata +75 -122
- data/.simplecov +0 -3
- data/Rakefile.rb +0 -9
- data/lib/jsi/base/to_rb.rb +0 -128
- data/lib/jsi/json/node.rb +0 -203
- data/lib/jsi/json/pointer.rb +0 -419
- data/lib/jsi/json-schema-fragments.rb +0 -61
- data/lib/jsi/json.rb +0 -10
- data/lib/jsi/pathed_node.rb +0 -118
- data/lib/jsi/typelike_modules.rb +0 -240
- data/resources/icons/AGPL-3.0.png +0 -0
- data/test/base_array_test.rb +0 -323
- data/test/base_hash_test.rb +0 -337
- data/test/base_test.rb +0 -486
- data/test/jsi_coder_test.rb +0 -85
- data/test/jsi_json_arraynode_test.rb +0 -150
- data/test/jsi_json_hashnode_test.rb +0 -132
- data/test/jsi_json_node_test.rb +0 -257
- data/test/jsi_json_pointer_test.rb +0 -102
- data/test/jsi_test.rb +0 -11
- data/test/jsi_typelike_as_json_test.rb +0 -53
- data/test/metaschema_node_test.rb +0 -19
- data/test/schema_module_test.rb +0 -21
- data/test/schema_test.rb +0 -208
- data/test/spreedly_openapi_test.rb +0 -8
- data/test/test_helper.rb +0 -97
- data/test/util_test.rb +0 -62
data/lib/jsi/typelike_modules.rb
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module JSI
|
|
4
|
-
# a module relating to objects that act like Hash or Array instances
|
|
5
|
-
module Typelike
|
|
6
|
-
# yields the content of the given param `object`. for objects which have a
|
|
7
|
-
# #modified_copy method of their own (JSI::Base, JSI::JSON::Node) that
|
|
8
|
-
# method is invoked with the given block. otherwise the given object itself
|
|
9
|
-
# is yielded.
|
|
10
|
-
#
|
|
11
|
-
# the given block must result in a modified copy of its block parameter
|
|
12
|
-
# (not destructively modifying the yielded content).
|
|
13
|
-
#
|
|
14
|
-
# @yield [Object] the content of the given object. the block should result
|
|
15
|
-
# in a (nondestructively) modified copy of this.
|
|
16
|
-
# @return [object.class] modified copy of the given object
|
|
17
|
-
def self.modified_copy(object, &block)
|
|
18
|
-
if object.respond_to?(:modified_copy)
|
|
19
|
-
object.modified_copy(&block)
|
|
20
|
-
else
|
|
21
|
-
return yield(object)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# recursive method to express the given argument object in json-compatible
|
|
26
|
-
# types of Hash, Array, and basic types of String/boolean/numeric/nil. this
|
|
27
|
-
# will raise TypeError if an object is given that is not a type that seems
|
|
28
|
-
# to be expressable as json.
|
|
29
|
-
#
|
|
30
|
-
# similar effect could be achieved by requiring 'json/add/core' and using
|
|
31
|
-
# #as_json, but I don't much care for how it represents classes that are
|
|
32
|
-
# not naturally expressable in JSON, and prefer not to load its
|
|
33
|
-
# monkey-patching.
|
|
34
|
-
#
|
|
35
|
-
# @param object [Object] the object to be converted to jsonifiability
|
|
36
|
-
# @return [Array, Hash, String, Boolean, NilClass, Numeric] jsonifiable
|
|
37
|
-
# expression of param object
|
|
38
|
-
# @raise [TypeError] when the object (or an object nested with a hash or
|
|
39
|
-
# array of object) cannot be expressed as json
|
|
40
|
-
def self.as_json(object, *opt)
|
|
41
|
-
if object.is_a?(JSI::PathedNode)
|
|
42
|
-
as_json(object.node_content, *opt)
|
|
43
|
-
elsif object.respond_to?(:to_hash)
|
|
44
|
-
(object.respond_to?(:map) ? object : object.to_hash).map do |k, v|
|
|
45
|
-
unless k.is_a?(Symbol) || k.respond_to?(:to_str)
|
|
46
|
-
raise(TypeError, "json object (hash) cannot be keyed with: #{k.pretty_inspect.chomp}")
|
|
47
|
-
end
|
|
48
|
-
{k.to_s => as_json(v, *opt)}
|
|
49
|
-
end.inject({}, &:update)
|
|
50
|
-
elsif object.respond_to?(:to_ary)
|
|
51
|
-
(object.respond_to?(:map) ? object : object.to_ary).map { |e| as_json(e, *opt) }
|
|
52
|
-
elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| object.is_a?(c) }
|
|
53
|
-
object
|
|
54
|
-
elsif object.is_a?(Symbol)
|
|
55
|
-
object.to_s
|
|
56
|
-
elsif object.is_a?(Set)
|
|
57
|
-
as_json(object.to_a, *opt)
|
|
58
|
-
elsif object.respond_to?(:as_json)
|
|
59
|
-
as_json(object.as_json(*opt), *opt)
|
|
60
|
-
else
|
|
61
|
-
raise(TypeError, "cannot express object as json: #{object.pretty_inspect.chomp}")
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# a module of methods for objects which behave like Hash but are not Hash.
|
|
67
|
-
#
|
|
68
|
-
# this module is intended to be internal to JSI. no guarantees or API promises
|
|
69
|
-
# are made for non-JSI classes including this module.
|
|
70
|
-
module Hashlike
|
|
71
|
-
# safe methods which can be delegated to #to_hash (which the includer is assumed to have defined).
|
|
72
|
-
# 'safe' means, in this context, nondestructive - methods which do not modify the receiver.
|
|
73
|
-
|
|
74
|
-
# methods which do not need to access the value.
|
|
75
|
-
SAFE_KEY_ONLY_METHODS = %w(each_key empty? has_key? include? key? keys length member? size)
|
|
76
|
-
SAFE_KEY_VALUE_METHODS = %w(< <= > >= any? assoc compact dig each_pair each_value fetch fetch_values has_value? invert key merge rassoc reject select to_h to_proc transform_values value? values values_at)
|
|
77
|
-
DESTRUCTIVE_METHODS = %w(clear delete delete_if keep_if reject! replace select! shift)
|
|
78
|
-
# these return a modified copy
|
|
79
|
-
safe_modified_copy_methods = %w(compact)
|
|
80
|
-
# select and reject will return a modified copy but need the yielded block variable value from #[]
|
|
81
|
-
safe_kv_block_modified_copy_methods = %w(select reject)
|
|
82
|
-
SAFE_METHODS = SAFE_KEY_ONLY_METHODS | SAFE_KEY_VALUE_METHODS
|
|
83
|
-
safe_to_hash_methods = SAFE_METHODS - safe_modified_copy_methods - safe_kv_block_modified_copy_methods
|
|
84
|
-
safe_to_hash_methods.each do |method_name|
|
|
85
|
-
define_method(method_name) { |*a, &b| to_hash.public_send(method_name, *a, &b) }
|
|
86
|
-
end
|
|
87
|
-
safe_modified_copy_methods.each do |method_name|
|
|
88
|
-
define_method(method_name) do |*a, &b|
|
|
89
|
-
modified_copy do |object_to_modify|
|
|
90
|
-
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_hash
|
|
91
|
-
responsive_object.public_send(method_name, *a, &b)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
safe_kv_block_modified_copy_methods.each do |method_name|
|
|
96
|
-
define_method(method_name) do |*a, &b|
|
|
97
|
-
modified_copy do |object_to_modify|
|
|
98
|
-
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_hash
|
|
99
|
-
responsive_object.public_send(method_name, *a) do |k, _v|
|
|
100
|
-
b.call(k, self[k])
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# the same as Hash#update
|
|
107
|
-
# @param other [#to_hash] the other hash to update this hash from
|
|
108
|
-
# @yield [key, oldval, newval] for entries with duplicate keys, the value of each duplicate key
|
|
109
|
-
# is determined by calling the block with the key, its value in hsh and its value in other_hash.
|
|
110
|
-
# @return self, updated with other
|
|
111
|
-
# @raise [TypeError] when `other` does not respond to #to_hash
|
|
112
|
-
def update(other, &block)
|
|
113
|
-
unless other.respond_to?(:to_hash)
|
|
114
|
-
raise(TypeError, "cannot update with argument that does not respond to #to_hash: #{other.pretty_inspect.chomp}")
|
|
115
|
-
end
|
|
116
|
-
self_respondingto_key = self.respond_to?(:key?) ? self : to_hash
|
|
117
|
-
other.to_hash.each_pair do |key, value|
|
|
118
|
-
if block_given? && self_respondingto_key.key?(key)
|
|
119
|
-
value = yield(key, self[key], value)
|
|
120
|
-
end
|
|
121
|
-
self[key] = value
|
|
122
|
-
end
|
|
123
|
-
self
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
alias_method :merge!, :update
|
|
127
|
-
|
|
128
|
-
# the same as Hash#merge
|
|
129
|
-
# @param other [#to_hash] the other hash to merge into this
|
|
130
|
-
# @yield [key, oldval, newval] for entries with duplicate keys, the value of each duplicate key
|
|
131
|
-
# is determined by calling the block with the key, its value in hsh and its value in other_hash.
|
|
132
|
-
# @return duplicate of this hash with the other hash merged in
|
|
133
|
-
# @raise [TypeError] when `other` does not respond to #to_hash
|
|
134
|
-
def merge(other, &block)
|
|
135
|
-
dup.update(other, &block)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# @return [String] basically the same #inspect as Hash, but has the
|
|
139
|
-
# class name and, if responsive, self's #object_group_text
|
|
140
|
-
def inspect
|
|
141
|
-
object_group_str = (respond_to?(:object_group_text) ? self.object_group_text : [self.class]).join(' ')
|
|
142
|
-
"\#{<#{object_group_str}>#{empty? ? '' : ' '}#{self.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join(', ')}}"
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
alias_method :to_s, :inspect
|
|
146
|
-
|
|
147
|
-
# pretty-prints a representation this node to the given printer
|
|
148
|
-
# @return [void]
|
|
149
|
-
def pretty_print(q)
|
|
150
|
-
object_group_str = (respond_to?(:object_group_text) ? object_group_text : [self.class]).join(' ')
|
|
151
|
-
q.text "\#{<#{object_group_str}>"
|
|
152
|
-
q.group_sub {
|
|
153
|
-
q.nest(2) {
|
|
154
|
-
q.breakable(any? { true } ? ' ' : '')
|
|
155
|
-
q.seplist(self, nil, :each_pair) { |k, v|
|
|
156
|
-
q.group {
|
|
157
|
-
q.pp k
|
|
158
|
-
q.text ' => '
|
|
159
|
-
q.pp v
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
q.breakable ''
|
|
165
|
-
q.text '}'
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# a module of methods for objects which behave like Array but are not Array.
|
|
170
|
-
#
|
|
171
|
-
# this module is intended to be internal to JSI. no guarantees or API promises
|
|
172
|
-
# are made for non-JSI classes including this module.
|
|
173
|
-
module Arraylike
|
|
174
|
-
# safe methods which can be delegated to #to_ary (which the includer is assumed to have defined).
|
|
175
|
-
# 'safe' means, in this context, nondestructive - methods which do not modify the receiver.
|
|
176
|
-
|
|
177
|
-
# methods which do not need to access the element.
|
|
178
|
-
SAFE_INDEX_ONLY_METHODS = %w(each_index empty? length size)
|
|
179
|
-
# there are some ambiguous ones that are omitted, like #sort, #map / #collect.
|
|
180
|
-
SAFE_INDEX_ELEMENT_METHODS = %w(| & * + - <=> abbrev assoc at bsearch bsearch_index combination compact count cycle dig drop drop_while fetch find_index first include? index join last pack permutation product reject repeated_combination repeated_permutation reverse reverse_each rindex rotate sample select shelljoin shuffle slice sort take take_while transpose uniq values_at zip)
|
|
181
|
-
DESTRUCTIVE_METHODS = %w(<< clear collect! compact! concat delete delete_at delete_if fill flatten! insert keep_if map! pop push reject! replace reverse! rotate! select! shift shuffle! slice! sort! sort_by! uniq! unshift)
|
|
182
|
-
|
|
183
|
-
# methods (well, method) that returns a modified copy and doesn't need any handling of block variable(s)
|
|
184
|
-
safe_modified_copy_methods = %w(compact)
|
|
185
|
-
|
|
186
|
-
# methods that return a modified copy and do need handling of block variables
|
|
187
|
-
safe_el_block_methods = %w(reject select)
|
|
188
|
-
|
|
189
|
-
SAFE_METHODS = SAFE_INDEX_ONLY_METHODS | SAFE_INDEX_ELEMENT_METHODS
|
|
190
|
-
safe_to_ary_methods = SAFE_METHODS - safe_modified_copy_methods - safe_el_block_methods
|
|
191
|
-
safe_to_ary_methods.each do |method_name|
|
|
192
|
-
define_method(method_name) { |*a, &b| to_ary.public_send(method_name, *a, &b) }
|
|
193
|
-
end
|
|
194
|
-
safe_modified_copy_methods.each do |method_name|
|
|
195
|
-
define_method(method_name) do |*a, &b|
|
|
196
|
-
modified_copy do |object_to_modify|
|
|
197
|
-
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_ary
|
|
198
|
-
responsive_object.public_send(method_name, *a, &b)
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
safe_el_block_methods.each do |method_name|
|
|
203
|
-
define_method(method_name) do |*a, &b|
|
|
204
|
-
modified_copy do |object_to_modify|
|
|
205
|
-
i = 0
|
|
206
|
-
responsive_object = object_to_modify.respond_to?(method_name) ? object_to_modify : object_to_modify.to_ary
|
|
207
|
-
responsive_object.public_send(method_name, *a) do |_e|
|
|
208
|
-
b.call(self[i]).tap { i += 1 }
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# @return [String] basically the same #inspect as Array, but has the
|
|
215
|
-
# class name and, if responsive, self's #object_group_text
|
|
216
|
-
def inspect
|
|
217
|
-
object_group_str = (respond_to?(:object_group_text) ? object_group_text : [self.class]).join(' ')
|
|
218
|
-
"\#[<#{object_group_str}>#{empty? ? '' : ' '}#{self.map { |e| e.inspect }.join(', ')}]"
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
alias_method :to_s, :inspect
|
|
222
|
-
|
|
223
|
-
# pretty-prints a representation this node to the given printer
|
|
224
|
-
# @return [void]
|
|
225
|
-
def pretty_print(q)
|
|
226
|
-
object_group_str = (respond_to?(:object_group_text) ? object_group_text : [self.class]).join(' ')
|
|
227
|
-
q.text "\#[<#{object_group_str}>"
|
|
228
|
-
q.group_sub {
|
|
229
|
-
q.nest(2) {
|
|
230
|
-
q.breakable(any? { true } ? ' ' : '')
|
|
231
|
-
q.seplist(self, nil, :each) { |e|
|
|
232
|
-
q.pp e
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
q.breakable ''
|
|
237
|
-
q.text ']'
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
end
|
|
Binary file
|
data/test/base_array_test.rb
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
require_relative 'test_helper'
|
|
2
|
-
|
|
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}] }
|
|
17
|
-
let(:schema_content) do
|
|
18
|
-
{
|
|
19
|
-
'description' => 'hash schema',
|
|
20
|
-
'type' => 'array',
|
|
21
|
-
'items' => [
|
|
22
|
-
{'type' => 'string'},
|
|
23
|
-
{'type' => 'object'},
|
|
24
|
-
{'type' => 'array', 'items' => {}},
|
|
25
|
-
],
|
|
26
|
-
}
|
|
27
|
-
end
|
|
28
|
-
let(:schema) { JSI::Schema.new(schema_content) }
|
|
29
|
-
let(:subject) { schema.new_jsi(instance) }
|
|
30
|
-
|
|
31
|
-
describe '#[] with a default that is a basic type' do
|
|
32
|
-
let(:schema_content) do
|
|
33
|
-
{
|
|
34
|
-
'type' => 'array',
|
|
35
|
-
'items' => {'default' => 'foo'},
|
|
36
|
-
}
|
|
37
|
-
end
|
|
38
|
-
describe 'default value' do
|
|
39
|
-
let(:instance) { [1] }
|
|
40
|
-
it 'returns the default value' do
|
|
41
|
-
assert_equal('foo', subject[2])
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
describe 'nondefault value (basic type)' do
|
|
45
|
-
let(:instance) { ['who'] }
|
|
46
|
-
it 'returns the nondefault value' do
|
|
47
|
-
assert_equal('who', subject[0])
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
describe 'nondefault value (nonbasic type)' do
|
|
51
|
-
let(:instance) { [[2]] }
|
|
52
|
-
it 'returns the nondefault value' do
|
|
53
|
-
assert_is_a(schema.items.jsi_schema_module, subject[0])
|
|
54
|
-
assert_equal([2], subject[0].as_json)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
describe '#[] with a default that is a nonbasic type' do
|
|
59
|
-
let(:schema_content) do
|
|
60
|
-
{
|
|
61
|
-
'type' => 'array',
|
|
62
|
-
'items' => {'default' => {'foo' => 2}},
|
|
63
|
-
}
|
|
64
|
-
end
|
|
65
|
-
describe 'default value' do
|
|
66
|
-
let(:instance) { [{'bar' => 3}] }
|
|
67
|
-
it 'returns the default value' do
|
|
68
|
-
assert_is_a(schema.items.jsi_schema_module, subject[1])
|
|
69
|
-
assert_equal({'foo' => 2}, subject[1].as_json)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
describe 'nondefault value (basic type)' do
|
|
73
|
-
let(:instance) { [true, 'who'] }
|
|
74
|
-
it 'returns the nondefault value' do
|
|
75
|
-
assert_equal('who', subject[1])
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
describe 'nondefault value (nonbasic type)' do
|
|
79
|
-
let(:instance) { [true, [2]] }
|
|
80
|
-
it 'returns the nondefault value' do
|
|
81
|
-
assert_is_a(schema.items.jsi_schema_module, subject[1])
|
|
82
|
-
assert_equal([2], subject[1].as_json)
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
describe 'arraylike []=' do
|
|
87
|
-
it 'sets an index' do
|
|
88
|
-
orig_2 = subject[2]
|
|
89
|
-
|
|
90
|
-
subject[2] = {'y' => 'z'}
|
|
91
|
-
|
|
92
|
-
assert_equal({'y' => 'z'}, subject[2].as_json)
|
|
93
|
-
assert_is_a(schema.items[2].jsi_schema_module, orig_2)
|
|
94
|
-
assert_is_a(schema.items[2].jsi_schema_module, subject[2])
|
|
95
|
-
end
|
|
96
|
-
it 'modifies the instance, visible to other references to the same instance' do
|
|
97
|
-
orig_instance = subject.jsi_instance
|
|
98
|
-
|
|
99
|
-
subject[2] = {'y' => 'z'}
|
|
100
|
-
|
|
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)
|
|
105
|
-
end
|
|
106
|
-
describe 'when the instance is not arraylike' do
|
|
107
|
-
let(:instance) { nil }
|
|
108
|
-
it 'errors' do
|
|
109
|
-
err = assert_raises(NoMethodError) { subject[2] = 0 }
|
|
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)
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
# these methods just delegate to Array so not going to test excessively
|
|
225
|
-
describe 'index only methods' do
|
|
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) }
|
|
230
|
-
end
|
|
231
|
-
describe 'index + element methods' do
|
|
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) }
|
|
239
|
-
require 'abbrev'
|
|
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([])) }
|
|
261
|
-
# due to differences in implementation between #assoc and #rassoc, the reason for which
|
|
262
|
-
# I cannot begin to fathom, assoc works but rassoc does not because rassoc has different
|
|
263
|
-
# type checking than assoc for the array(like) array elements.
|
|
264
|
-
# compare:
|
|
265
|
-
# assoc: https://github.com/ruby/ruby/blob/v2_5_0/array.c#L3780-L3813
|
|
266
|
-
# rassoc: https://github.com/ruby/ruby/blob/v2_5_0/array.c#L3815-L3847
|
|
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')) }
|
|
269
|
-
it('#repeated_combination') { assert_equal([[]], subject.repeated_combination(0).to_a) }
|
|
270
|
-
it('#repeated_permutation') { assert_equal([[]], subject.repeated_permutation(0).to_a) }
|
|
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
|
|
297
|
-
end
|
|
298
|
-
describe 'modified copy methods' do
|
|
299
|
-
it('#reject') { assert_equal(schema.new_jsi(['foo']), subject.reject { |e| e != 'foo' }) }
|
|
300
|
-
it('#reject block var') do
|
|
301
|
-
subj_a = subject.to_a
|
|
302
|
-
subject.reject { |e| assert_equal(e, subj_a.shift) }
|
|
303
|
-
end
|
|
304
|
-
it('#select') { assert_equal(schema.new_jsi(['foo']), subject.select { |e| e == 'foo' }) }
|
|
305
|
-
it('#select block var') do
|
|
306
|
-
subj_a = subject.to_a
|
|
307
|
-
subject.select { |e| assert_equal(e, subj_a.shift) }
|
|
308
|
-
end
|
|
309
|
-
it('#compact') { assert_equal(subject, subject.compact) }
|
|
310
|
-
describe 'at a depth' do
|
|
311
|
-
it('#select') do
|
|
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)
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
JSI::Arraylike::DESTRUCTIVE_METHODS.each do |destructive_method_name|
|
|
319
|
-
it("does not respond to destructive method #{destructive_method_name}") do
|
|
320
|
-
assert(!subject.respond_to?(destructive_method_name))
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
end
|