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