hana 1.3.2 → 1.3.7
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 +5 -5
- data/Manifest.txt +3 -2
- data/README.md +1 -1
- data/Rakefile +6 -2
- data/lib/hana.rb +78 -27
- data/test/helper.rb +18 -1
- data/test/json-patch-tests/.editorconfig +10 -0
- data/test/json-patch-tests/.npmignore +2 -0
- data/test/json-patch-tests/package.json +15 -0
- data/test/json-patch-tests/tests.json +101 -4
- data/test/test_hana.rb +48 -0
- metadata +23 -17
- data/.autotest +0 -8
- data/CHANGELOG.rdoc +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8f7c301531d8d60e3267883dc0cd34f1366151fd5b876a2439fb296a971248ee
|
4
|
+
data.tar.gz: 8aaa875ad968a75b54bfc5526137430c69cbbd1090dc47eb3997ec2557c645aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 934c2ddf91379c64cd7b748f940df6fb120fdf79b8667522c7a20e305ed92a92a1ecc01148029c3ddd50b759671aa890a2ecac40bfe1c02b8980dbda7e9086f4
|
7
|
+
data.tar.gz: 8d15b436be7dc1c61e6ff6364dfbdc1a5fe09c0962e15efd858bab4143f8725212a6166480be170950eb4908bb38d26075ae64b49e638600c06649cb8ff9f5ca
|
data/Manifest.txt
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
.autotest
|
2
|
-
CHANGELOG.rdoc
|
3
1
|
Manifest.txt
|
4
2
|
README.md
|
5
3
|
Rakefile
|
6
4
|
lib/hana.rb
|
7
5
|
test/helper.rb
|
6
|
+
test/json-patch-tests/.editorconfig
|
7
|
+
test/json-patch-tests/.npmignore
|
8
8
|
test/json-patch-tests/README.md
|
9
|
+
test/json-patch-tests/package.json
|
9
10
|
test/json-patch-tests/spec_tests.json
|
10
11
|
test/json-patch-tests/tests.json
|
11
12
|
test/mine.json
|
data/README.md
CHANGED
@@ -35,7 +35,7 @@ patch.apply('foo' => 'bar') # => {'baz' => 'qux', 'foo' => 'bar'}
|
|
35
35
|
|
36
36
|
(The MIT License)
|
37
37
|
|
38
|
-
Copyright (c) 2012-
|
38
|
+
Copyright (c) 2012-2020 Aaron Patterson
|
39
39
|
|
40
40
|
Permission is hereby granted, free of charge, to any person obtaining
|
41
41
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
|
4
|
+
begin
|
5
|
+
require 'hoe'
|
6
|
+
rescue LoadError
|
7
|
+
Gem.install 'hoe'
|
8
|
+
retry
|
9
|
+
end
|
5
10
|
|
6
11
|
Hoe.plugins.delete :rubyforge
|
7
12
|
Hoe.plugin :minitest
|
@@ -12,7 +17,6 @@ Hoe.spec 'hana' do
|
|
12
17
|
developer('Aaron Patterson', 'aaron@tenderlovemaking.com')
|
13
18
|
license 'MIT'
|
14
19
|
self.readme_file = 'README.md'
|
15
|
-
self.history_file = 'CHANGELOG.rdoc'
|
16
20
|
self.extra_rdoc_files = FileList['*.rdoc']
|
17
21
|
extra_dev_deps << ["minitest", "~> 5.0"]
|
18
22
|
end
|
data/lib/hana.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hana
|
2
|
-
VERSION = '1.3.
|
4
|
+
VERSION = '1.3.7'
|
3
5
|
|
4
6
|
class Pointer
|
5
7
|
include Enumerable
|
6
8
|
|
9
|
+
class Exception < StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
class FormatError < Exception
|
13
|
+
end
|
14
|
+
|
7
15
|
def initialize path
|
8
16
|
@path = Pointer.parse path
|
9
17
|
end
|
@@ -21,7 +29,7 @@ module Hana
|
|
21
29
|
return nil unless o
|
22
30
|
|
23
31
|
if Array === o
|
24
|
-
raise Patch::IndexError unless part =~ /\A\d
|
32
|
+
raise Patch::IndexError unless part =~ /\A(?:\d|[1-9]\d+)\Z/
|
25
33
|
part = part.to_i
|
26
34
|
end
|
27
35
|
o[part]
|
@@ -30,6 +38,11 @@ module Hana
|
|
30
38
|
|
31
39
|
def self.parse path
|
32
40
|
return [''] if path == '/'
|
41
|
+
return [] if path == ''
|
42
|
+
|
43
|
+
unless path.start_with? '/'
|
44
|
+
raise FormatError, "JSON Pointer should start with a slash"
|
45
|
+
end
|
33
46
|
|
34
47
|
parts = path.sub(/^\//, '').split(/(?<!\^)\//).each { |part|
|
35
48
|
part.gsub!(/\^[\/^]|~[01]/) { |m| ESC[m] }
|
@@ -60,12 +73,18 @@ module Hana
|
|
60
73
|
class ObjectOperationOnArrayException < Exception
|
61
74
|
end
|
62
75
|
|
76
|
+
class InvalidObjectOperationException < Exception
|
77
|
+
end
|
78
|
+
|
63
79
|
class IndexError < Exception
|
64
80
|
end
|
65
81
|
|
66
82
|
class MissingTargetException < Exception
|
67
83
|
end
|
68
84
|
|
85
|
+
class InvalidPath < Exception
|
86
|
+
end
|
87
|
+
|
69
88
|
def initialize is
|
70
89
|
@is = is
|
71
90
|
end
|
@@ -74,7 +93,7 @@ module Hana
|
|
74
93
|
|
75
94
|
def apply doc
|
76
95
|
@is.inject(doc) { |d, ins|
|
77
|
-
send VALID.fetch(ins[
|
96
|
+
send VALID.fetch(ins['op'].strip) { |k|
|
78
97
|
raise Exception, "bad method `#{k}`"
|
79
98
|
}, ins, d
|
80
99
|
}
|
@@ -82,98 +101,122 @@ module Hana
|
|
82
101
|
|
83
102
|
private
|
84
103
|
|
85
|
-
PATH = 'path' # :nodoc:
|
86
104
|
FROM = 'from' # :nodoc:
|
87
105
|
VALUE = 'value' # :nodoc:
|
88
|
-
OP = 'op' # :nodoc:
|
89
106
|
|
90
107
|
def add ins, doc
|
91
|
-
|
108
|
+
path = get_path ins
|
109
|
+
list = Pointer.parse path
|
92
110
|
key = list.pop
|
93
111
|
dest = Pointer.eval list, doc
|
94
112
|
obj = ins.fetch VALUE
|
95
113
|
|
96
|
-
raise(MissingTargetException, ins[
|
114
|
+
raise(MissingTargetException, "target location '#{ins['path']}' does not exist") unless dest
|
97
115
|
|
98
116
|
if key
|
99
117
|
add_op dest, key, obj
|
100
118
|
else
|
101
|
-
|
119
|
+
if doc.equal? dest
|
120
|
+
doc = obj
|
121
|
+
else
|
122
|
+
dest.replace obj
|
123
|
+
end
|
102
124
|
end
|
103
125
|
doc
|
104
126
|
end
|
105
127
|
|
106
128
|
def move ins, doc
|
129
|
+
path = get_path ins
|
107
130
|
from = Pointer.parse ins.fetch FROM
|
108
|
-
to = Pointer.parse
|
131
|
+
to = Pointer.parse path
|
109
132
|
from_key = from.pop
|
110
133
|
key = to.pop
|
111
134
|
src = Pointer.eval from, doc
|
112
135
|
dest = Pointer.eval to, doc
|
113
136
|
|
137
|
+
raise(MissingTargetException, "target location '#{ins['path']}' does not exist") unless dest
|
138
|
+
|
114
139
|
obj = rm_op src, from_key
|
115
140
|
add_op dest, key, obj
|
116
141
|
doc
|
117
142
|
end
|
118
143
|
|
119
144
|
def copy ins, doc
|
145
|
+
path = get_path ins
|
120
146
|
from = Pointer.parse ins.fetch FROM
|
121
|
-
to = Pointer.parse
|
147
|
+
to = Pointer.parse path
|
122
148
|
from_key = from.pop
|
123
149
|
key = to.pop
|
124
150
|
src = Pointer.eval from, doc
|
125
151
|
dest = Pointer.eval to, doc
|
126
152
|
|
127
153
|
if Array === src
|
128
|
-
raise Patch::
|
154
|
+
raise Patch::ObjectOperationOnArrayException, "cannot apply non-numeric key '#{key}' to array" unless from_key =~ /\A\d+\Z/
|
129
155
|
obj = src.fetch from_key.to_i
|
130
156
|
else
|
131
|
-
|
157
|
+
begin
|
158
|
+
obj = src.fetch from_key
|
159
|
+
rescue KeyError, NoMethodError
|
160
|
+
raise Hana::Patch::MissingTargetException, "'from' location '#{ins.fetch FROM}' does not exist"
|
161
|
+
end
|
132
162
|
end
|
133
163
|
|
164
|
+
raise(MissingTargetException, "target location '#{ins['path']}' does not exist") unless dest
|
165
|
+
|
134
166
|
add_op dest, key, obj
|
135
167
|
doc
|
136
168
|
end
|
137
169
|
|
138
170
|
def test ins, doc
|
139
|
-
|
171
|
+
path = get_path ins
|
172
|
+
expected = Pointer.new(path).eval doc
|
140
173
|
|
141
174
|
unless expected == ins.fetch(VALUE)
|
142
|
-
raise FailedTestException.new(ins[
|
175
|
+
raise FailedTestException.new(ins['path'], ins[VALUE])
|
143
176
|
end
|
144
177
|
doc
|
145
178
|
end
|
146
179
|
|
147
180
|
def replace ins, doc
|
148
|
-
|
181
|
+
path = get_path ins
|
182
|
+
list = Pointer.parse path
|
149
183
|
key = list.pop
|
150
184
|
obj = Pointer.eval list, doc
|
151
185
|
|
152
186
|
return ins.fetch VALUE unless key
|
153
187
|
|
154
|
-
|
155
|
-
|
156
|
-
obj[key.to_i] = ins.fetch VALUE
|
157
|
-
else
|
158
|
-
obj[key] = ins.fetch VALUE
|
159
|
-
end
|
188
|
+
rm_op obj, key
|
189
|
+
add_op obj, key, ins.fetch(VALUE)
|
160
190
|
doc
|
161
191
|
end
|
162
192
|
|
163
193
|
def remove ins, doc
|
164
|
-
|
194
|
+
path = get_path ins
|
195
|
+
list = Pointer.parse path
|
165
196
|
key = list.pop
|
166
197
|
obj = Pointer.eval list, doc
|
167
198
|
rm_op obj, key
|
168
199
|
doc
|
169
200
|
end
|
170
201
|
|
202
|
+
def get_path ins
|
203
|
+
unless ins.key?('path')
|
204
|
+
raise Hana::Patch::InvalidPath, "missing 'path' parameter"
|
205
|
+
end
|
206
|
+
|
207
|
+
unless ins['path']
|
208
|
+
raise Hana::Patch::InvalidPath, "null is not valid value for 'path'"
|
209
|
+
end
|
210
|
+
|
211
|
+
ins['path']
|
212
|
+
end
|
213
|
+
|
171
214
|
def check_index obj, key
|
172
215
|
return -1 if key == '-'
|
173
216
|
|
174
|
-
raise ObjectOperationOnArrayException unless key =~ /\A-?\d+\Z/
|
217
|
+
raise ObjectOperationOnArrayException, "cannot apply non-numeric key '#{key}' to array" unless key =~ /\A-?\d+\Z/
|
175
218
|
idx = key.to_i
|
176
|
-
raise OutOfBoundsException if idx > obj.length || idx < 0
|
219
|
+
raise OutOfBoundsException, "key '#{key}' is out of bounds for array" if idx > obj.length || idx < 0
|
177
220
|
idx
|
178
221
|
end
|
179
222
|
|
@@ -181,16 +224,24 @@ module Hana
|
|
181
224
|
if Array === dest
|
182
225
|
dest.insert check_index(dest, key), obj
|
183
226
|
else
|
227
|
+
raise Patch::InvalidObjectOperationException, "cannot add key '#{key}' to non-object" unless Hash === dest
|
184
228
|
dest[key] = obj
|
185
229
|
end
|
186
230
|
end
|
187
231
|
|
188
232
|
def rm_op obj, key
|
189
233
|
if Array === obj
|
190
|
-
raise Patch::
|
191
|
-
|
234
|
+
raise Patch::ObjectOperationOnArrayException, "cannot apply non-numeric key '#{key}' to array" unless key =~ /\A\d+\Z/
|
235
|
+
key = key.to_i
|
236
|
+
raise Patch::OutOfBoundsException, "key '#{key}' is out of bounds for array" if key >= obj.length
|
237
|
+
obj.delete_at key
|
192
238
|
else
|
193
|
-
|
239
|
+
begin
|
240
|
+
raise Patch::MissingTargetException, "key '#{key}' not found" unless obj&.key? key
|
241
|
+
obj.delete key
|
242
|
+
rescue ::NoMethodError
|
243
|
+
raise Patch::InvalidObjectOperationException, "cannot remove key '#{key}' from non-object"
|
244
|
+
end
|
194
245
|
end
|
195
246
|
end
|
196
247
|
end
|
data/test/helper.rb
CHANGED
@@ -12,7 +12,16 @@ module Hana
|
|
12
12
|
tests.each_with_index do |test, i|
|
13
13
|
next unless test['doc']
|
14
14
|
|
15
|
-
|
15
|
+
method = "test_#{test['comment'] || i }"
|
16
|
+
loop do
|
17
|
+
if method_defined? method
|
18
|
+
method = "test_#{test['comment'] || i } x"
|
19
|
+
else
|
20
|
+
break
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
define_method(method) do
|
16
25
|
skip "disabled" if test['disabled']
|
17
26
|
|
18
27
|
doc = test['doc']
|
@@ -50,12 +59,20 @@ module Hana
|
|
50
59
|
[Hana::Patch::IndexError, Hana::Patch::ObjectOperationOnArrayException]
|
51
60
|
when /bad number$/ then
|
52
61
|
[Hana::Patch::IndexError, Hana::Patch::ObjectOperationOnArrayException]
|
62
|
+
when /removing a nonexistent (field|index)/ then
|
63
|
+
[Hana::Patch::MissingTargetException, Hana::Patch::OutOfBoundsException]
|
64
|
+
when /test op should reject the array value, it has leading zeros/ then
|
65
|
+
[Hana::Patch::IndexError]
|
53
66
|
when /missing '(from|value)' parameter/ then
|
54
67
|
[KeyError]
|
55
68
|
when /Unrecognized op 'spam'/ then
|
56
69
|
[Hana::Patch::Exception]
|
70
|
+
when /missing 'path'|null is not valid value for 'path'/ then
|
71
|
+
[Hana::Patch::InvalidPath]
|
57
72
|
when /missing|non-existent/ then
|
58
73
|
[Hana::Patch::MissingTargetException]
|
74
|
+
when /JSON Pointer should start with a slash/ then
|
75
|
+
[Hana::Pointer::FormatError]
|
59
76
|
else
|
60
77
|
[Hana::Patch::FailedTestException]
|
61
78
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"name": "json-patch-test-suite",
|
3
|
+
"version": "1.1.0",
|
4
|
+
"description": "JSON Patch RFC 6902 test suite",
|
5
|
+
"repository": "github:json-patch/json-patch-tests",
|
6
|
+
"homepage": "https://github.com/json-patch/json-patch-tests",
|
7
|
+
"bugs": "https://github.com/json-patch/json-patch-tests/issues",
|
8
|
+
"keywords": [
|
9
|
+
"JSON",
|
10
|
+
"Patch",
|
11
|
+
"test",
|
12
|
+
"suite"
|
13
|
+
],
|
14
|
+
"license": "Apache-2.0"
|
15
|
+
}
|
@@ -55,6 +55,21 @@
|
|
55
55
|
"expected": "bar",
|
56
56
|
"disabled": true },
|
57
57
|
|
58
|
+
{ "comment": "replace object document with array document?",
|
59
|
+
"doc": {},
|
60
|
+
"patch": [{"op": "add", "path": "", "value": []}],
|
61
|
+
"expected": [] },
|
62
|
+
|
63
|
+
{ "comment": "replace array document with object document?",
|
64
|
+
"doc": [],
|
65
|
+
"patch": [{"op": "add", "path": "", "value": {}}],
|
66
|
+
"expected": {} },
|
67
|
+
|
68
|
+
{ "comment": "append to root array document?",
|
69
|
+
"doc": [],
|
70
|
+
"patch": [{"op": "add", "path": "/-", "value": "hi"}],
|
71
|
+
"expected": ["hi"] },
|
72
|
+
|
58
73
|
{ "comment": "Add, / target",
|
59
74
|
"doc": {},
|
60
75
|
"patch": [ {"op": "add", "path": "/", "value":1 } ],
|
@@ -187,6 +202,11 @@
|
|
187
202
|
"patch": [{"op": "replace", "path": "", "value": {"baz": "qux"}}],
|
188
203
|
"expected": {"baz": "qux"} },
|
189
204
|
|
205
|
+
{ "comment": "test replace with missing parent key should fail",
|
206
|
+
"doc": {"bar": "baz"},
|
207
|
+
"patch": [{"op": "replace", "path": "/foo/bar", "value": false}],
|
208
|
+
"error": "replace op should fail with missing parent key" },
|
209
|
+
|
190
210
|
{ "comment": "spurious patch properties",
|
191
211
|
"doc": {"foo": 1},
|
192
212
|
"patch": [{"op": "test", "path": "/foo", "value": 1, "spurious": 1}],
|
@@ -194,6 +214,7 @@
|
|
194
214
|
|
195
215
|
{ "doc": {"foo": null},
|
196
216
|
"patch": [{"op": "test", "path": "/foo", "value": null}],
|
217
|
+
"expected": {"foo": null},
|
197
218
|
"comment": "null value should be valid obj property" },
|
198
219
|
|
199
220
|
{ "doc": {"foo": null},
|
@@ -223,14 +244,17 @@
|
|
223
244
|
|
224
245
|
{ "doc": {"foo": {"foo": 1, "bar": 2}},
|
225
246
|
"patch": [{"op": "test", "path": "/foo", "value": {"bar": 2, "foo": 1}}],
|
247
|
+
"expected": {"foo": {"foo": 1, "bar": 2}},
|
226
248
|
"comment": "test should pass despite rearrangement" },
|
227
249
|
|
228
250
|
{ "doc": {"foo": [{"foo": 1, "bar": 2}]},
|
229
251
|
"patch": [{"op": "test", "path": "/foo", "value": [{"bar": 2, "foo": 1}]}],
|
252
|
+
"expected": {"foo": [{"foo": 1, "bar": 2}]},
|
230
253
|
"comment": "test should pass despite (nested) rearrangement" },
|
231
254
|
|
232
255
|
{ "doc": {"foo": {"bar": [1, 2, 5, 4]}},
|
233
256
|
"patch": [{"op": "test", "path": "/foo", "value": {"bar": [1, 2, 5, 4]}}],
|
257
|
+
"expected": {"foo": {"bar": [1, 2, 5, 4]}},
|
234
258
|
"comment": "test should pass - no error" },
|
235
259
|
|
236
260
|
{ "doc": {"foo": {"bar": [1, 2, 5, 4]}},
|
@@ -244,7 +268,8 @@
|
|
244
268
|
|
245
269
|
{ "comment": "Empty-string element",
|
246
270
|
"doc": { "": 1 },
|
247
|
-
"patch": [{"op": "test", "path": "/", "value": 1}]
|
271
|
+
"patch": [{"op": "test", "path": "/", "value": 1}],
|
272
|
+
"expected": { "": 1 } },
|
248
273
|
|
249
274
|
{ "doc": {
|
250
275
|
"foo": ["bar", "baz"],
|
@@ -268,8 +293,23 @@
|
|
268
293
|
{"op": "test", "path": "/i\\j", "value": 5},
|
269
294
|
{"op": "test", "path": "/k\"l", "value": 6},
|
270
295
|
{"op": "test", "path": "/ ", "value": 7},
|
271
|
-
{"op": "test", "path": "/m~0n", "value": 8}]
|
272
|
-
|
296
|
+
{"op": "test", "path": "/m~0n", "value": 8}],
|
297
|
+
"expected": {
|
298
|
+
"": 0,
|
299
|
+
" ": 7,
|
300
|
+
"a/b": 1,
|
301
|
+
"c%d": 2,
|
302
|
+
"e^f": 3,
|
303
|
+
"foo": [
|
304
|
+
"bar",
|
305
|
+
"baz"
|
306
|
+
],
|
307
|
+
"g|h": 4,
|
308
|
+
"i\\j": 5,
|
309
|
+
"k\"l": 6,
|
310
|
+
"m~n": 8
|
311
|
+
}
|
312
|
+
},
|
273
313
|
{ "comment": "Move to same location has no effect",
|
274
314
|
"doc": {"foo": 1},
|
275
315
|
"patch": [{"op": "move", "from": "/foo", "path": "/foo"}],
|
@@ -343,6 +383,21 @@
|
|
343
383
|
"patch": [{"op": "add", "path": "/1e0", "value": "bar"}],
|
344
384
|
"error": "add op shouldn't add to array with bad number" },
|
345
385
|
|
386
|
+
{ "comment": "missing 'path' parameter",
|
387
|
+
"doc": {},
|
388
|
+
"patch": [ { "op": "add", "value": "bar" } ],
|
389
|
+
"error": "missing 'path' parameter" },
|
390
|
+
|
391
|
+
{ "comment": "'path' parameter with null value",
|
392
|
+
"doc": {},
|
393
|
+
"patch": [ { "op": "add", "path": null, "value": "bar" } ],
|
394
|
+
"error": "null is not valid value for 'path'" },
|
395
|
+
|
396
|
+
{ "comment": "invalid JSON Pointer token",
|
397
|
+
"doc": {},
|
398
|
+
"patch": [ { "op": "add", "path": "foo", "value": "bar" } ],
|
399
|
+
"error": "JSON Pointer should start with a slash" },
|
400
|
+
|
346
401
|
{ "comment": "missing 'value' parameter to add",
|
347
402
|
"doc": [ 1 ],
|
348
403
|
"patch": [ { "op": "add", "path": "/-" } ],
|
@@ -368,11 +423,21 @@
|
|
368
423
|
"patch": [ { "op": "copy", "path": "/-" } ],
|
369
424
|
"error": "missing 'from' parameter" },
|
370
425
|
|
426
|
+
{ "comment": "missing from location to copy",
|
427
|
+
"doc": { "foo": 1 },
|
428
|
+
"patch": [ { "op": "copy", "from": "/bar", "path": "/foo" } ],
|
429
|
+
"error": "missing 'from' location" },
|
430
|
+
|
371
431
|
{ "comment": "missing from parameter to move",
|
372
432
|
"doc": { "foo": 1 },
|
373
433
|
"patch": [ { "op": "move", "path": "" } ],
|
374
434
|
"error": "missing 'from' parameter" },
|
375
435
|
|
436
|
+
{ "comment": "missing from location to move",
|
437
|
+
"doc": { "foo": 1 },
|
438
|
+
"patch": [ { "op": "move", "from": "/bar", "path": "/foo" } ],
|
439
|
+
"error": "missing 'from' location" },
|
440
|
+
|
376
441
|
{ "comment": "duplicate ops",
|
377
442
|
"doc": { "foo": "bar" },
|
378
443
|
"patch": [ { "op": "add", "path": "/baz", "value": "qux",
|
@@ -383,5 +448,37 @@
|
|
383
448
|
{ "comment": "unrecognized op should fail",
|
384
449
|
"doc": {"foo": 1},
|
385
450
|
"patch": [{"op": "spam", "path": "/foo", "value": 1}],
|
386
|
-
"error": "Unrecognized op 'spam'" }
|
451
|
+
"error": "Unrecognized op 'spam'" },
|
452
|
+
|
453
|
+
{ "comment": "test with bad array number that has leading zeros",
|
454
|
+
"doc": ["foo", "bar"],
|
455
|
+
"patch": [{"op": "test", "path": "/00", "value": "foo"}],
|
456
|
+
"error": "test op should reject the array value, it has leading zeros" },
|
457
|
+
|
458
|
+
{ "comment": "test with bad array number that has leading zeros",
|
459
|
+
"doc": ["foo", "bar"],
|
460
|
+
"patch": [{"op": "test", "path": "/01", "value": "bar"}],
|
461
|
+
"error": "test op should reject the array value, it has leading zeros" },
|
462
|
+
|
463
|
+
{ "comment": "Removing nonexistent field",
|
464
|
+
"doc": {"foo" : "bar"},
|
465
|
+
"patch": [{"op": "remove", "path": "/baz"}],
|
466
|
+
"error": "removing a nonexistent field should fail" },
|
467
|
+
|
468
|
+
{ "comment": "Removing deep nonexistent path",
|
469
|
+
"doc": {"foo" : "bar"},
|
470
|
+
"patch": [{"op": "remove", "path": "/missing1/missing2"}],
|
471
|
+
"error": "removing a nonexistent field should fail" },
|
472
|
+
|
473
|
+
{ "comment": "Removing nonexistent index",
|
474
|
+
"doc": ["foo", "bar"],
|
475
|
+
"patch": [{"op": "remove", "path": "/2"}],
|
476
|
+
"error": "removing a nonexistent index should fail" },
|
477
|
+
|
478
|
+
{ "comment": "Patch with different capitalisation than doc",
|
479
|
+
"doc": {"foo":"bar"},
|
480
|
+
"patch": [{"op": "add", "path": "/FOO", "value": "BAR"}],
|
481
|
+
"expected": {"foo": "bar", "FOO": "BAR"}
|
482
|
+
}
|
483
|
+
|
387
484
|
]
|
data/test/test_hana.rb
CHANGED
@@ -69,4 +69,52 @@ class TestHana < Hana::TestCase
|
|
69
69
|
pointer = Hana::Pointer.new '/foo/bar/baz'
|
70
70
|
assert_nil pointer.eval('foo' => nil)
|
71
71
|
end
|
72
|
+
|
73
|
+
def test_remove_missing_object_key
|
74
|
+
patch = Hana::Patch.new [
|
75
|
+
{ 'op' => 'remove', 'path' => '/missing_key' }
|
76
|
+
]
|
77
|
+
assert_raises(Hana::Patch::MissingTargetException) do
|
78
|
+
patch.apply('foo' => 'bar')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_remove_deep_missing_path
|
83
|
+
patch = Hana::Patch.new [
|
84
|
+
{ 'op' => 'remove', 'path' => '/missing_key1/missing_key2' }
|
85
|
+
]
|
86
|
+
assert_raises(Hana::Patch::MissingTargetException) do
|
87
|
+
patch.apply('foo' => 'bar')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_remove_missing_array_index
|
92
|
+
patch = Hana::Patch.new [
|
93
|
+
{ 'op' => 'remove', 'path' => '/1' }
|
94
|
+
]
|
95
|
+
assert_raises(Hana::Patch::OutOfBoundsException) do
|
96
|
+
patch.apply([0])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_remove_missing_object_key_in_array
|
101
|
+
patch = Hana::Patch.new [
|
102
|
+
{ 'op' => 'remove', 'path' => '/1/baz' }
|
103
|
+
]
|
104
|
+
assert_raises(Hana::Patch::MissingTargetException) do
|
105
|
+
patch.apply([
|
106
|
+
{ 'foo' => 'bar' },
|
107
|
+
{ 'foo' => 'bar' }
|
108
|
+
])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_replace_missing_key
|
113
|
+
patch = Hana::Patch.new [
|
114
|
+
{ 'op' => 'replace', 'path' => '/missing_key/field', 'value' => 'asdf' }
|
115
|
+
]
|
116
|
+
assert_raises(Hana::Patch::MissingTargetException) do
|
117
|
+
patch.apply('foo' => 'bar')
|
118
|
+
end
|
119
|
+
end
|
72
120
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -16,60 +16,66 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '5.
|
19
|
+
version: '5.14'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '5.
|
26
|
+
version: '5.14'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rdoc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '7'
|
34
37
|
type: :development
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '4.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '7'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: hoe
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
53
|
+
version: '3.22'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - "~>"
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
60
|
+
version: '3.22'
|
55
61
|
description: Implementation of [JSON Patch][1] and [JSON Pointer][2] RFC.
|
56
62
|
email:
|
57
63
|
- aaron@tenderlovemaking.com
|
58
64
|
executables: []
|
59
65
|
extensions: []
|
60
66
|
extra_rdoc_files:
|
61
|
-
- CHANGELOG.rdoc
|
62
67
|
- Manifest.txt
|
63
68
|
- README.md
|
64
69
|
files:
|
65
|
-
- ".autotest"
|
66
|
-
- CHANGELOG.rdoc
|
67
70
|
- Manifest.txt
|
68
71
|
- README.md
|
69
72
|
- Rakefile
|
70
73
|
- lib/hana.rb
|
71
74
|
- test/helper.rb
|
75
|
+
- test/json-patch-tests/.editorconfig
|
76
|
+
- test/json-patch-tests/.npmignore
|
72
77
|
- test/json-patch-tests/README.md
|
78
|
+
- test/json-patch-tests/package.json
|
73
79
|
- test/json-patch-tests/spec_tests.json
|
74
80
|
- test/json-patch-tests/tests.json
|
75
81
|
- test/mine.json
|
@@ -78,8 +84,9 @@ files:
|
|
78
84
|
homepage: http://github.com/tenderlove/hana
|
79
85
|
licenses:
|
80
86
|
- MIT
|
81
|
-
metadata:
|
82
|
-
|
87
|
+
metadata:
|
88
|
+
homepage_uri: http://github.com/tenderlove/hana
|
89
|
+
post_install_message:
|
83
90
|
rdoc_options:
|
84
91
|
- "--main"
|
85
92
|
- README.md
|
@@ -96,9 +103,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
103
|
- !ruby/object:Gem::Version
|
97
104
|
version: '0'
|
98
105
|
requirements: []
|
99
|
-
|
100
|
-
|
101
|
-
signing_key:
|
106
|
+
rubygems_version: 3.2.0.rc.2
|
107
|
+
signing_key:
|
102
108
|
specification_version: 4
|
103
109
|
summary: Implementation of [JSON Patch][1] and [JSON Pointer][2] RFC.
|
104
110
|
test_files: []
|
data/.autotest
DELETED
data/CHANGELOG.rdoc
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
Wed May 22 19:28:10 2013 Aaron Patterson <aaron@tenderlovemaking.com>
|
2
|
-
|
3
|
-
* All IETF compliant
|
4
|
-
|
5
|
-
Fri Sep 7 18:54:17 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
6
|
-
|
7
|
-
* Bumping the version.
|
8
|
-
|
9
|
-
Fri Sep 7 18:53:16 2012 Aaron Patterson <aaron@tenderlovemaking.com>
|
10
|
-
|
11
|
-
* validate commands an raise an exception Just In Case
|
12
|
-
|