tentd 0.0.1
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.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +9 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/bin/tent-server +3 -0
- data/lib/tentd.rb +31 -0
- data/lib/tentd/api.rb +58 -0
- data/lib/tentd/api/apps.rb +196 -0
- data/lib/tentd/api/authentication_finalize.rb +12 -0
- data/lib/tentd/api/authentication_lookup.rb +27 -0
- data/lib/tentd/api/authentication_verification.rb +50 -0
- data/lib/tentd/api/authorizable.rb +21 -0
- data/lib/tentd/api/authorization.rb +14 -0
- data/lib/tentd/api/core_profile_data.rb +45 -0
- data/lib/tentd/api/followers.rb +218 -0
- data/lib/tentd/api/followings.rb +241 -0
- data/lib/tentd/api/groups.rb +161 -0
- data/lib/tentd/api/middleware.rb +32 -0
- data/lib/tentd/api/posts.rb +373 -0
- data/lib/tentd/api/profile.rb +78 -0
- data/lib/tentd/api/router.rb +123 -0
- data/lib/tentd/api/router/caching_headers.rb +49 -0
- data/lib/tentd/api/router/extract_params.rb +88 -0
- data/lib/tentd/api/router/serialize_response.rb +38 -0
- data/lib/tentd/api/user_lookup.rb +10 -0
- data/lib/tentd/core_ext/hash/slice.rb +29 -0
- data/lib/tentd/datamapper/array_property.rb +23 -0
- data/lib/tentd/datamapper/query.rb +19 -0
- data/lib/tentd/json_patch.rb +181 -0
- data/lib/tentd/model.rb +30 -0
- data/lib/tentd/model/app.rb +68 -0
- data/lib/tentd/model/app_authorization.rb +113 -0
- data/lib/tentd/model/follower.rb +105 -0
- data/lib/tentd/model/following.rb +100 -0
- data/lib/tentd/model/group.rb +24 -0
- data/lib/tentd/model/mention.rb +19 -0
- data/lib/tentd/model/notification_subscription.rb +56 -0
- data/lib/tentd/model/permissible.rb +227 -0
- data/lib/tentd/model/permission.rb +28 -0
- data/lib/tentd/model/post.rb +178 -0
- data/lib/tentd/model/post_attachment.rb +27 -0
- data/lib/tentd/model/post_version.rb +64 -0
- data/lib/tentd/model/profile_info.rb +80 -0
- data/lib/tentd/model/random_public_id.rb +46 -0
- data/lib/tentd/model/serializable.rb +58 -0
- data/lib/tentd/model/type_properties.rb +36 -0
- data/lib/tentd/model/user.rb +39 -0
- data/lib/tentd/model/user_scoped.rb +14 -0
- data/lib/tentd/notifications.rb +13 -0
- data/lib/tentd/notifications/girl_friday.rb +30 -0
- data/lib/tentd/notifications/sidekiq.rb +50 -0
- data/lib/tentd/tent_type.rb +20 -0
- data/lib/tentd/tent_version.rb +41 -0
- data/lib/tentd/version.rb +3 -0
- data/spec/fabricators/app_authorizations_fabricator.rb +5 -0
- data/spec/fabricators/apps_fabricator.rb +11 -0
- data/spec/fabricators/followers_fabricator.rb +14 -0
- data/spec/fabricators/followings_fabricator.rb +17 -0
- data/spec/fabricators/groups_fabricator.rb +3 -0
- data/spec/fabricators/mentions_fabricator.rb +3 -0
- data/spec/fabricators/notification_subscriptions_fabricator.rb +4 -0
- data/spec/fabricators/permissions_fabricator.rb +1 -0
- data/spec/fabricators/post_attachments_fabricator.rb +8 -0
- data/spec/fabricators/post_versions_fabricator.rb +12 -0
- data/spec/fabricators/posts_fabricator.rb +12 -0
- data/spec/fabricators/profile_infos_fabricator.rb +30 -0
- data/spec/integration/api/apps_spec.rb +466 -0
- data/spec/integration/api/followers_spec.rb +535 -0
- data/spec/integration/api/followings_spec.rb +688 -0
- data/spec/integration/api/groups_spec.rb +207 -0
- data/spec/integration/api/posts_spec.rb +874 -0
- data/spec/integration/api/profile_spec.rb +285 -0
- data/spec/integration/api/router_spec.rb +102 -0
- data/spec/integration/model/app_authorization_spec.rb +59 -0
- data/spec/integration/model/app_spec.rb +63 -0
- data/spec/integration/model/follower_spec.rb +344 -0
- data/spec/integration/model/following_spec.rb +97 -0
- data/spec/integration/model/group_spec.rb +39 -0
- data/spec/integration/model/notification_subscription_spec.rb +145 -0
- data/spec/integration/model/post_spec.rb +658 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/expect_server.rb +3 -0
- data/spec/support/json_request.rb +54 -0
- data/spec/support/with_constant.rb +23 -0
- data/spec/support/with_warnings.rb +6 -0
- data/spec/unit/api/authentication_finalize_spec.rb +45 -0
- data/spec/unit/api/authentication_lookup_spec.rb +65 -0
- data/spec/unit/api/authentication_verification_spec.rb +50 -0
- data/spec/unit/api/authorizable_spec.rb +50 -0
- data/spec/unit/api/authorization_spec.rb +44 -0
- data/spec/unit/api/caching_headers_spec.rb +121 -0
- data/spec/unit/core_profile_data_spec.rb +64 -0
- data/spec/unit/json_patch_spec.rb +407 -0
- data/spec/unit/tent_type_spec.rb +28 -0
- data/spec/unit/tent_version_spec.rb +68 -0
- data/tentd.gemspec +36 -0
- metadata +435 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe TentD::API::CoreProfileData do
|
|
4
|
+
let(:tent_profile_type_uri) { "https://tent.io/types/info/core/v0.1.0" }
|
|
5
|
+
let(:entity_url) { "https://smith.example.com" }
|
|
6
|
+
let(:another_entity_url) { "https://alex.example.org" }
|
|
7
|
+
let(:data) do
|
|
8
|
+
{
|
|
9
|
+
"https://tent.io/types/info/core/v0.1.5" => {
|
|
10
|
+
"licenses" => [],
|
|
11
|
+
"entity" => entity_url,
|
|
12
|
+
},
|
|
13
|
+
"https://tent.io/types/info/core/v0.1.1" => {
|
|
14
|
+
"licenses" => [],
|
|
15
|
+
"entity" => entity_url,
|
|
16
|
+
},
|
|
17
|
+
"https://tent.io/types/info/core/v0.2.0" => {
|
|
18
|
+
"licenses" => [],
|
|
19
|
+
"entity" => entity_url,
|
|
20
|
+
},
|
|
21
|
+
"https://tent.io/types/info/musci/v0.1.0" => {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
describe '#expected_version' do
|
|
26
|
+
it 'should return TentVersion representing sever tent profile type uri version' do
|
|
27
|
+
with_constants "TentD::Model::ProfileInfo::TENT_PROFILE_TYPE_URI" => tent_profile_type_uri do
|
|
28
|
+
expect(described_class.new(data).expected_version).to eq(TentD::TentVersion.new('0.1.0'))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe '#versions' do
|
|
34
|
+
it 'should return array of TentVersions found in data matching core info type' do
|
|
35
|
+
expect(described_class.new(data).versions).to eq([
|
|
36
|
+
TentD::TentVersion.new('0.1.1'),
|
|
37
|
+
TentD::TentVersion.new('0.1.5'),
|
|
38
|
+
TentD::TentVersion.new('0.2.0')
|
|
39
|
+
])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#version' do
|
|
44
|
+
it 'should return closest compatible version' do
|
|
45
|
+
expect(described_class.new(data).version).to eq(TentD::TentVersion.new('0.1.1'))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#version_key' do
|
|
50
|
+
it 'should return full url of version' do
|
|
51
|
+
expect(described_class.new(data).version_key).to eq("https://tent.io/types/info/core/v0.1.1")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe '#entity?(entity)' do
|
|
56
|
+
it 'should return true if entity matches' do
|
|
57
|
+
expect(described_class.new(data).entity?(entity_url)).to be_true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'should return false if entity does not match' do
|
|
61
|
+
expect(described_class.new(data).entity?(another_entity_url)).to be_false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe TentD::JsonPatch::HashPointer do
|
|
4
|
+
context 'when finding pointer' do
|
|
5
|
+
it 'should find nested hash' do
|
|
6
|
+
hash = { "a" => { "b" => { "c" => "foo" } } }
|
|
7
|
+
pointer = described_class.new(hash, "a/b/c")
|
|
8
|
+
expect(pointer.value).to eq("foo")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should find position in array' do
|
|
12
|
+
hash = { "a" => ["foo", "bar", "baz"] }
|
|
13
|
+
pointer = described_class.new(hash, "a/1")
|
|
14
|
+
expect(pointer.value).to eq("bar")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should throw exception if key doesn't exist" do
|
|
18
|
+
hash = { "a" => "foo" }
|
|
19
|
+
pointer = described_class.new(hash, "a/b/c")
|
|
20
|
+
expect(lambda { pointer.value }).to raise_error(described_class::InvalidPointer)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should throw exception if array position is outsize index range" do
|
|
24
|
+
hash = { "a" => ["foo", "bar", "baz"] }
|
|
25
|
+
pointer = described_class.new(hash, "a/3")
|
|
26
|
+
expect(lambda { pointer.value }).to raise_error(described_class::InvalidPointer)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'when setting pointer' do
|
|
31
|
+
it "should set nested hash key" do
|
|
32
|
+
pointer = described_class.new({}, "a/b/c")
|
|
33
|
+
pointer.value = "foo"
|
|
34
|
+
expect(pointer.value).to eq("foo")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should set value at array index' do
|
|
38
|
+
hash = { "a" => ["foo", "bar"] }
|
|
39
|
+
pointer = described_class.new(hash, "a/1")
|
|
40
|
+
pointer.value = "baz"
|
|
41
|
+
expect(hash["a"]).to be_an(Array)
|
|
42
|
+
expect(pointer.value).to eq("baz")
|
|
43
|
+
expect(described_class.new(hash, "a/2").value).to eq("bar")
|
|
44
|
+
|
|
45
|
+
hash = { "a" => { "b" => ["foo", "baz"] } }
|
|
46
|
+
pointer = described_class.new(hash, "a/b/1")
|
|
47
|
+
pointer.value = "bar"
|
|
48
|
+
expect(hash["a"]["b"]).to be_an(Array)
|
|
49
|
+
expect(pointer.value).to eq("bar")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'when deleting pointer' do
|
|
54
|
+
it 'should delete key from object' do
|
|
55
|
+
hash = { "a" => { "b" => { "c" => "foo" } } }
|
|
56
|
+
pointer = described_class.new(hash, "a/b/c")
|
|
57
|
+
pointer.delete
|
|
58
|
+
expect(hash).to eq({ "a" => { "b" => {} } })
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'should delete index from array' do
|
|
62
|
+
hash = { "a" => { "b" => ["foo", "baz", "bar"] } }
|
|
63
|
+
pointer = described_class.new(hash, "a/b/1")
|
|
64
|
+
pointer.delete
|
|
65
|
+
expect(hash).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'should throw exception if key does not exist' do
|
|
69
|
+
hash = {}
|
|
70
|
+
pointer = described_class.new(hash, "a")
|
|
71
|
+
expect( lambda { pointer.delete }).to raise_error(described_class::InvalidPointer)
|
|
72
|
+
expect(hash).to eq({})
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'should throw exception if index of array does not exist' do
|
|
76
|
+
hash = { "a" => { "b" => ["foo", "bar"] } }
|
|
77
|
+
pointer = described_class.new(hash, "a/b/2")
|
|
78
|
+
expect( lambda { pointer.delete }).to raise_error(described_class::InvalidPointer)
|
|
79
|
+
expect(hash).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when moving pointer' do
|
|
84
|
+
it 'should move key to another key' do
|
|
85
|
+
hash = { "a" => { "b" => { "c" => "foo" } } }
|
|
86
|
+
pointer = described_class.new(hash, "a/b")
|
|
87
|
+
pointer.move_to "/b"
|
|
88
|
+
expect(hash).to eq({ "a" => {}, "b" => { "c" => "foo" } })
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'should move array index to another index' do
|
|
92
|
+
hash = { "a" => { "b" => ["foo", "bar"] } }
|
|
93
|
+
pointer = described_class.new(hash, "a/b/0")
|
|
94
|
+
pointer.move_to "a/b/1"
|
|
95
|
+
expect(hash).to eq({ "a" => { "b" => ["bar", "foo"] } })
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'should throw exception if to would overwrite another key' do
|
|
99
|
+
hash = { "a" => { "b" => ["foo", "bar"] } }
|
|
100
|
+
pointer = described_class.new(hash, "a/b/0")
|
|
101
|
+
expect( lambda { pointer.move_to "a/b/c" } ).
|
|
102
|
+
to raise_error(described_class::InvalidPointer)
|
|
103
|
+
expect(hash).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe '#exists?' do
|
|
108
|
+
it 'should return false if key not in hash' do
|
|
109
|
+
hash = { "a" => { "b" => { "foo" => "bar" } } }
|
|
110
|
+
pointer = described_class.new(hash, "a/b/c")
|
|
111
|
+
expect(pointer.exists?).to be_false
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should return false if index not in array' do
|
|
115
|
+
hash = { "a" => { "b" => ["foo", "bar"] } }
|
|
116
|
+
pointer = described_class.new(hash, "a/b/2")
|
|
117
|
+
expect(pointer.exists?).to be_false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should return true if key in hash' do
|
|
121
|
+
hash = { "a" => { "b" => { "foo" => "bar" } } }
|
|
122
|
+
pointer = described_class.new(hash, "a/b")
|
|
123
|
+
expect(pointer.exists?).to be_true
|
|
124
|
+
|
|
125
|
+
hash = { "a" => "baz" }
|
|
126
|
+
pointer = described_class.new(hash, "a/b")
|
|
127
|
+
expect(pointer.exists?).to be_true
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'should return true if index in array' do
|
|
131
|
+
hash = { "a" => { "b" => ["foo", "bar"] } }
|
|
132
|
+
pointer = described_class.new(hash, "a/b/1")
|
|
133
|
+
expect(pointer.exists?).to be_true
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe TentD::JsonPatch do
|
|
139
|
+
describe 'add' do
|
|
140
|
+
it 'should add new value at specified location' do
|
|
141
|
+
object = {}
|
|
142
|
+
patch_object = [{ "add" => "a/b/c", "value" => ["foo", "bar", "baz"] }]
|
|
143
|
+
TentD::JsonPatch.merge(object, patch_object)
|
|
144
|
+
expect(object).to be_a(Hash)
|
|
145
|
+
expect(object["a"]["b"]["c"]).to eq(["foo", "bar", "baz"])
|
|
146
|
+
|
|
147
|
+
object = { "a" => {} }
|
|
148
|
+
patch_object = [{ "add" => "a/b/c", "value" => ["foo", "bar", "baz"] }]
|
|
149
|
+
TentD::JsonPatch.merge(object, patch_object)
|
|
150
|
+
expect(object).to be_a(Hash)
|
|
151
|
+
expect(object["a"]["b"]["c"]).to eq(["foo", "bar", "baz"])
|
|
152
|
+
|
|
153
|
+
object = { "a" => { "b" => {} } }
|
|
154
|
+
patch_object = [{ "add" => "a/b/c", "value" => ["foo", "bar", "baz"] }]
|
|
155
|
+
TentD::JsonPatch.merge(object, patch_object)
|
|
156
|
+
expect(object).to be_a(Hash)
|
|
157
|
+
expect(object["a"]["b"]["c"]).to eq(["foo", "bar", "baz"])
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'should throw exception if specified location exists' do
|
|
161
|
+
object = { "a" => "foo" }
|
|
162
|
+
patch_object = [{ "add" => "a/b/c", "value" => ["foo", "bar", "baz"] }]
|
|
163
|
+
expect( lambda { TentD::JsonPatch.merge(object, patch_object) } ).
|
|
164
|
+
to raise_error(described_class::ObjectExists)
|
|
165
|
+
expect(object["a"]).to eq("foo")
|
|
166
|
+
|
|
167
|
+
object = { "a" => { "b" => "foo" } }
|
|
168
|
+
patch_object = [{ "add" => "a/b/c", "value" => ["foo", "bar", "baz"] }]
|
|
169
|
+
expect( lambda { TentD::JsonPatch.merge(object, patch_object) } ).
|
|
170
|
+
to raise_error(described_class::ObjectExists)
|
|
171
|
+
expect(object["a"]).to eq("b" => "foo")
|
|
172
|
+
|
|
173
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
174
|
+
patch_object = [{ "add" => "a/b/c", "value" => ["foo", "bar", "baz"] }]
|
|
175
|
+
expect( lambda { TentD::JsonPatch.merge(object, patch_object) } ).
|
|
176
|
+
to raise_error(described_class::ObjectExists)
|
|
177
|
+
expect(object["a"]).to eq("b" => { "c" => "foo" })
|
|
178
|
+
|
|
179
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
180
|
+
patch_object = [{ "add" => "a/b/c/d/e/f/g", "value" => ["foo", "bar", "baz"] }]
|
|
181
|
+
expect( lambda { TentD::JsonPatch.merge(object, patch_object) } ).
|
|
182
|
+
to raise_error(described_class::ObjectExists)
|
|
183
|
+
expect(object["a"]).to eq("b" => { "c" => "foo" })
|
|
184
|
+
|
|
185
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
186
|
+
patch_object = [{ "add" => "a/b/c/d/e/f/g", "value" => ["foo", "bar", "baz"] }]
|
|
187
|
+
expect( lambda { TentD::JsonPatch.merge(object, patch_object) } ).
|
|
188
|
+
to raise_error(described_class::ObjectExists)
|
|
189
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
context 'when pointer is an array' do
|
|
193
|
+
it 'should add new value at specified index' do
|
|
194
|
+
object = { "a" => ["foo", "bar"] }
|
|
195
|
+
patch_object = [{ "add" => "a/1", "value" => "baz" }]
|
|
196
|
+
TentD::JsonPatch.merge(object, patch_object)
|
|
197
|
+
expect(object["a"]).to eq(["foo", "baz", "bar"])
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
describe 'remove' do
|
|
203
|
+
it 'should remove specified key' do
|
|
204
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
205
|
+
patch_object = [{ "remove" => "a/b/c" }]
|
|
206
|
+
described_class.merge(object, patch_object)
|
|
207
|
+
expect(object).to eq({ "a" => { "b" => {} } })
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'should throw exception if specified key does not exist' do
|
|
211
|
+
object = { "a" => { "b" => {} } }
|
|
212
|
+
patch_object = [{ "remove" => "a/b/c" }]
|
|
213
|
+
expect( lambda { described_class.merge(object, patch_object) } ).
|
|
214
|
+
to raise_error(described_class::ObjectNotFound)
|
|
215
|
+
expect(object).to eq({ "a" => { "b" => {} } })
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
context 'when pointer is an array' do
|
|
219
|
+
it 'should remove specified index' do
|
|
220
|
+
object = { "a" => { "b" => ["foo", "baz", "bar"] } }
|
|
221
|
+
patch_object = [{ "remove" => "a/b/1" }]
|
|
222
|
+
described_class.merge(object, patch_object)
|
|
223
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'should throw exception if specified index does not exist' do
|
|
227
|
+
object = { "a" => { "b" => ["foo"] } }
|
|
228
|
+
patch_object = [{ "remove" => "a/b/1" }]
|
|
229
|
+
expect( lambda { described_class.merge(object, patch_object) } ).
|
|
230
|
+
to raise_error(described_class::ObjectNotFound)
|
|
231
|
+
expect(object).to eq({ "a" => { "b" => ["foo"] } })
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
describe 'replace' do
|
|
237
|
+
it 'should replace specified key value' do
|
|
238
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
239
|
+
patch_object = [{ "replace" => "a", "value" => ["foo", "bar"] }]
|
|
240
|
+
described_class.merge(object, patch_object)
|
|
241
|
+
expect(object).to eq({ "a" => ["foo", "bar"] })
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it 'should replace specified index of array' do
|
|
245
|
+
object = { "a" => { "b" => ["foo", "baz"] } }
|
|
246
|
+
patch_object = [{ "replace" => "a/b/1", "value" => "bar" }]
|
|
247
|
+
described_class.merge(object, patch_object)
|
|
248
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it 'should throw exception if specified key does not exist' do
|
|
252
|
+
object = { "a" => { "b" => {} } }
|
|
253
|
+
patch_object = [{ "replace" => "a/b/c", "value" => "foo" }]
|
|
254
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
255
|
+
to raise_error(described_class::ObjectNotFound)
|
|
256
|
+
expect(object).to eq({ "a" => { "b" => {} } })
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it 'should throw exception if specified index does not exist' do
|
|
260
|
+
object = { "a" => [] }
|
|
261
|
+
patch_object = [{ "replace" => "a/1", "value" => "bar" }]
|
|
262
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
263
|
+
to raise_error(described_class::ObjectNotFound)
|
|
264
|
+
expect(object).to eq({ "a" => [] })
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
describe 'move' do
|
|
269
|
+
it 'should move specified key to new key' do
|
|
270
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
271
|
+
patch_object = [{ "move" => "a/b", "to" => "/b" }]
|
|
272
|
+
described_class.merge(object, patch_object)
|
|
273
|
+
expect(object).to eq({ "a" => {}, "b" => { "c" => "foo" } })
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it 'should move specified index to new index' do
|
|
277
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
278
|
+
patch_object = [{ "move" => "a/b/0", "to" => "a/b/1" }]
|
|
279
|
+
described_class.merge(object, patch_object)
|
|
280
|
+
expect(object).to eq({ "a" => { "b" => ["bar", "foo"] } })
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it 'should throw exception if specified key does not exist' do
|
|
284
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
285
|
+
patch_object = [{ "move" => "a/b/c/d", "to" => "/b" }]
|
|
286
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
287
|
+
to raise_error(described_class::ObjectNotFound)
|
|
288
|
+
expect(object).to eq({ "a" => { "b" => { "c" => "foo" } } })
|
|
289
|
+
|
|
290
|
+
object = { "a" => { "b" => "foo" } }
|
|
291
|
+
patch_object = [{ "move" => "a/b/c", "to" => "a" }]
|
|
292
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
293
|
+
to raise_error(described_class::ObjectNotFound)
|
|
294
|
+
expect(object).to eq({ "a" => { "b" => "foo" } })
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it 'should throw exception if specified index does not exist' do
|
|
298
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
299
|
+
patch_object = [{ "move" => "a/b/2", "to" => "a/b/0" }]
|
|
300
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
301
|
+
to raise_error(described_class::ObjectNotFound)
|
|
302
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'should throw exception if to key would overwrite another' do
|
|
306
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
307
|
+
patch_object = [{ "move" => "a/b/0", "to" => "a/b/c" }]
|
|
308
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
309
|
+
to raise_error(described_class::ObjectNotFound)
|
|
310
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
describe 'copy' do
|
|
315
|
+
it 'should copy specified key value to new key' do
|
|
316
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
317
|
+
patch_object = [{ "copy" => "a/b/c", "to" => "/c" }]
|
|
318
|
+
described_class.merge(object, patch_object)
|
|
319
|
+
expect(object).to eq({ "a" => { "b" => { "c" => "foo" } }, "c" => "foo" })
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it 'should copy specified index value to new index' do
|
|
323
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
324
|
+
patch_object = [{ "copy" => "a/b/0", "to" => "a/b/2" }]
|
|
325
|
+
described_class.merge(object, patch_object)
|
|
326
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar", "foo"] } })
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it 'should throw exception if specified key does not exist' do
|
|
330
|
+
object = { "a" => { "b" => { "c" => "foo" } } }
|
|
331
|
+
patch_object = [{ "copy" => "a/b/c/d", "to" => "/b" }]
|
|
332
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
333
|
+
to raise_error(described_class::ObjectNotFound)
|
|
334
|
+
expect(object).to eq({ "a" => { "b" => { "c" => "foo" } } })
|
|
335
|
+
|
|
336
|
+
object = { "a" => { "b" => "foo" } }
|
|
337
|
+
patch_object = [{ "copy" => "a/b/c", "to" => "a" }]
|
|
338
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
339
|
+
to raise_error(described_class::ObjectNotFound)
|
|
340
|
+
expect(object).to eq({ "a" => { "b" => "foo" } })
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it 'should throw exception if specified index does not exist' do
|
|
344
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
345
|
+
patch_object = [{ "copy" => "a/b/2", "to" => "a/b/0" }]
|
|
346
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
347
|
+
to raise_error(described_class::ObjectNotFound)
|
|
348
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it 'should throw exception if to key would overwrite another' do
|
|
352
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
353
|
+
patch_object = [{ "copy" => "a/b/0", "to" => "a/b/c" }]
|
|
354
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
355
|
+
to raise_error(described_class::ObjectExists)
|
|
356
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
describe 'test' do
|
|
361
|
+
it 'should throw exception if specified key does not exist' do
|
|
362
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
363
|
+
patch_object = [{ "test" => "a/c" }]
|
|
364
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
365
|
+
to raise_error(described_class::ObjectNotFound)
|
|
366
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it 'should throw exception if specified key does not equal specified value' do
|
|
370
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
371
|
+
patch_object = [{ "test" => "a/b/0", "value" => "chunkybacon" }]
|
|
372
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
373
|
+
to raise_error(described_class::ObjectNotFound)
|
|
374
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it 'should throw exception if specified index does not exist' do
|
|
378
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
379
|
+
patch_object = [{ "test" => "a/b/3" }]
|
|
380
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
381
|
+
to raise_error(described_class::ObjectNotFound)
|
|
382
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it 'should throw exception if specified index does not equal specified value' do
|
|
386
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
387
|
+
patch_object = [{ "test" => "a/b/0", "value" => "chunkybacon" }]
|
|
388
|
+
expect(lambda { described_class.merge(object, patch_object) }).
|
|
389
|
+
to raise_error(described_class::ObjectNotFound)
|
|
390
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it 'should not do anything if key exists and matches specified value' do
|
|
394
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
395
|
+
patch_object = [{ "test" => "a/b", "value" => ["foo", "bar"] }]
|
|
396
|
+
described_class.merge(object, patch_object)
|
|
397
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it 'should not do anything if index exists and matches specified value' do
|
|
401
|
+
object = { "a" => { "b" => ["foo", "bar"] } }
|
|
402
|
+
patch_object = [{ "test" => "a/b/0", "value" => "foo" }]
|
|
403
|
+
described_class.merge(object, patch_object)
|
|
404
|
+
expect(object).to eq({ "a" => { "b" => ["foo", "bar"] } })
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
end
|