ashikawa-core 0.12.0 → 0.13.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.
@@ -21,6 +21,19 @@ describe Ashikawa::Core::Connection do
21
21
  end
22
22
  end
23
23
 
24
+ it 'should include include the x-arango-version header in each request' do
25
+ [:get, :post, :put, :delete].each do |http_verb|
26
+ request_stub.send(http_verb, '/_db/_system/_api/my/path') do |request|
27
+ expect(request[:request_headers][:'X-Arango-Version']).to eq '20200'
28
+ [200, response_headers, JSON.generate({ 'name' => 'dude' })]
29
+ end
30
+
31
+ subject.send_request 'my/path', http_verb => {}
32
+
33
+ request_stub.verify_stubbed_calls
34
+ end
35
+ end
36
+
24
37
  it 'should send a get request' do
25
38
  request_stub.get('/_db/_system/_api/my/path') do
26
39
  [200, response_headers, JSON.generate({ 'name' => 'dude' })]
@@ -205,6 +218,40 @@ describe Ashikawa::Core::Connection do
205
218
  request_stub.verify_stubbed_calls
206
219
  end
207
220
 
221
+ context 'handle 404 in the gharial module' do
222
+ let(:request_url) { '/_db/_system/_api/gharial/vertex/42' }
223
+
224
+ it 'should raise GraphNotFoundException if the graph could not be found' do
225
+ request_stub.get(request_url) do
226
+ [404, response_headers, { 'errorMessage' => 'graph not found' }]
227
+ end
228
+
229
+ expect { subject.send_request 'gharial/vertex/42' }.to raise_error(Ashikawa::Core::GraphNotFoundException)
230
+
231
+ request_stub.verify_stubbed_calls
232
+ end
233
+
234
+ it 'should raise CollectionNotFoundException the collection could not be found' do
235
+ request_stub.get(request_url) do
236
+ [404, response_headers, { 'errorMessage' => 'collection not found' }]
237
+ end
238
+
239
+ expect { subject.send_request 'gharial/vertex/42' }.to raise_error(Ashikawa::Core::CollectionNotFoundException)
240
+
241
+ request_stub.verify_stubbed_calls
242
+ end
243
+
244
+ it 'should raise DocumentNotFoundException the document could not be found' do
245
+ request_stub.get(request_url) do
246
+ [404, response_headers, { 'errorMessage' => 'document not found' }]
247
+ end
248
+
249
+ expect { subject.send_request 'gharial/vertex/42' }.to raise_error(Ashikawa::Core::DocumentNotFoundException)
250
+
251
+ request_stub.verify_stubbed_calls
252
+ end
253
+ end
254
+
208
255
  it 'should raise an exception for unknown pathes' do
209
256
  request_stub.get('/_db/_system/_api/unknown_path/4590/333') do
210
257
  [404, response_headers, '']
@@ -208,5 +208,116 @@ describe Ashikawa::Core::Database do
208
208
 
209
209
  expect(subject.create_transaction(js_function, collections)).to be(transaction)
210
210
  end
211
+
212
+ context 'managing graphs' do
213
+ let(:raw_graph) { double('RawGraph') }
214
+ let(:gharial_response) { double('GharialResponse') }
215
+ let(:graph) { instance_double(Ashikawa::Core::Graph) }
216
+
217
+ before do
218
+ allow(gharial_response).to receive(:[]).with('graph').and_return(raw_graph)
219
+ end
220
+
221
+ it 'should fetch a single graph if it exists' do
222
+ expect(connection).to receive(:send_request)
223
+ .with('gharial/my_awesome_graph')
224
+ .and_return(gharial_response)
225
+
226
+ expect(Ashikawa::Core::Graph).to receive(:new)
227
+ .with(subject, raw_graph)
228
+ .and_return(graph)
229
+
230
+ expect(subject.graph('my_awesome_graph')).to eq graph
231
+ end
232
+
233
+ it "should create a single graph if it doesn't exist" do
234
+ expect(connection).to receive(:send_request).with('gharial/my_awesome_graph') do
235
+ raise Ashikawa::Core::GraphNotFoundException
236
+ end
237
+
238
+ expect(subject).to receive(:create_graph).with('my_awesome_graph').and_return(graph)
239
+
240
+ expect(subject.graph('my_awesome_graph')).to eq graph
241
+ end
242
+
243
+ it 'should create a graph' do
244
+ expect(connection).to receive(:send_request)
245
+ .with('gharial', post: { name: 'my_awesome_graph' })
246
+ .and_return(gharial_response)
247
+
248
+ expect(Ashikawa::Core::Graph).to receive(:new)
249
+ .with(subject, raw_graph)
250
+ .and_return(graph)
251
+
252
+ expect(subject.create_graph('my_awesome_graph')).to eq graph
253
+ end
254
+
255
+ it 'should create a single graph with list of edge_definitions' do
256
+ create_params = {
257
+ name: 'my_awesome_graph',
258
+ edgeDefinitions: [
259
+ { collection: 'visited', from: ['ponies'], to: ['places'] }
260
+ ]
261
+ }
262
+ expect(connection).to receive(:send_request)
263
+ .with('gharial', post: create_params)
264
+ .and_return(gharial_response)
265
+
266
+ expect(Ashikawa::Core::Graph).to receive(:new)
267
+ .with(subject, raw_graph)
268
+ .and_return(graph)
269
+
270
+ options = {
271
+ edge_definitions: [
272
+ {
273
+ collection: 'visited',
274
+ from: ['ponies'],
275
+ to: ['places']
276
+ }
277
+ ]
278
+ }
279
+
280
+ expect(subject.create_graph('my_awesome_graph', options)).to eq graph
281
+ end
282
+
283
+ it 'should create a single graph with list of orphan_collections' do
284
+ create_params = {
285
+ name: 'my_awesome_graph',
286
+ orphanCollections: ['i_am_alone']
287
+ }
288
+ expect(connection).to receive(:send_request)
289
+ .with('gharial', post: create_params)
290
+ .and_return(gharial_response)
291
+
292
+ expect(Ashikawa::Core::Graph).to receive(:new)
293
+ .with(subject, raw_graph)
294
+ .and_return(graph)
295
+
296
+ options = {
297
+ orphan_collections: ['i_am_alone']
298
+ }
299
+
300
+ expect(subject.create_graph('my_awesome_graph', options)).to eq graph
301
+
302
+ end
303
+
304
+ it 'should fetch a list of all graphs in the database' do
305
+ raw_list_of_graphs = double('ListOfGraphs')
306
+ allow(raw_list_of_graphs).to receive(:[])
307
+ .with('graphs')
308
+ .and_return([raw_graph])
309
+
310
+ expect(connection).to receive(:send_request)
311
+ .with('gharial')
312
+ .and_return(raw_list_of_graphs)
313
+
314
+ expect(Ashikawa::Core::Graph).to receive(:new)
315
+ .with(subject, raw_graph)
316
+ .and_return(graph)
317
+
318
+ expect(subject.graphs).to eq [graph]
319
+ end
320
+ end
321
+
211
322
  end
212
323
  end
@@ -57,6 +57,22 @@ describe Ashikawa::Core::Document do
57
57
  end
58
58
  end
59
59
 
60
+ describe 'initialized with a garaph' do
61
+ let(:graph) { double('Ashikawa::Core::Graph', name: 'my-graph') }
62
+ let(:additional_data_with_graph) { { graph: graph, more_info: more_info } }
63
+ subject { Ashikawa::Core::Document.new(database, raw_data, additional_data_with_graph) }
64
+
65
+ its(['more_info']) { should eq(more_info) }
66
+ its(:graph) { should eq(graph) }
67
+
68
+ it 'should send requests through the graph module' do
69
+ expect(database).to receive(:send_request)
70
+ .with("gharial/my-graph/vertex/#{id}", {})
71
+
72
+ subject.send(:send_request_for_document, {})
73
+ end
74
+ end
75
+
60
76
  describe 'initialized document with ID' do
61
77
  subject { Ashikawa::Core::Document.new(database, raw_data) }
62
78
 
@@ -0,0 +1,105 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'unit/spec_helper'
3
+ require 'ashikawa-core/edge_collection'
4
+ require 'ashikawa-core/document'
5
+ require 'ashikawa-core/graph'
6
+ require 'ashikawa-core/database'
7
+
8
+ describe Ashikawa::Core::EdgeCollection do
9
+ let(:database) { instance_double('Ashikawa::Core::Database') }
10
+ let(:raw_collection) do
11
+ {
12
+ 'id' => '60768679',
13
+ 'name' => 'relation',
14
+ 'status' => 3,
15
+ 'type' => 3,
16
+ 'error' => false,
17
+ 'code' => 200
18
+ }
19
+ end
20
+ let(:graph) { instance_double('Ashikawa::Core::Graph', name: 'my_graph') }
21
+ let(:new_edge) { instance_double('Ashikawa::Core::Edge') }
22
+ let(:raw_edge) { double('RawEdge') }
23
+ let(:post_response) { { 'edge' => { '_key' => '123' } } }
24
+
25
+ context 'an initialized edge collection' do
26
+ subject { Ashikawa::Core::EdgeCollection.new(database, raw_collection, graph) }
27
+
28
+ it 'should be a subclass of Collection' do
29
+ expect(subject).to be_kind_of Ashikawa::Core::Collection
30
+ end
31
+
32
+ it 'should have a reference to its graph' do
33
+ expect(subject.graph).to eq graph
34
+ end
35
+
36
+ context 'adding edges' do
37
+ let(:this_document) { instance_double('Ashikawa::Core::Document', id: 'this_document_id') }
38
+ let(:that_document) { instance_double('Ashikawa::Core::Document', id: 'that_document_id') }
39
+
40
+ before do
41
+ allow(subject).to receive(:send_request)
42
+ .with('gharial/my_graph/edge/relation/', post: { _from: 'this_document_id', _to: 'that_document_id' })
43
+ .and_return(post_response)
44
+
45
+ allow(subject).to receive(:fetch)
46
+ .with('123')
47
+ .and_return(new_edge)
48
+ end
49
+
50
+ it 'should add a directed relation between to vertices' do
51
+ expect(subject).to receive(:send_request)
52
+ .with('gharial/my_graph/edge/relation/', post: { _from: 'this_document_id', _to: 'that_document_id' })
53
+ .and_return(post_response)
54
+
55
+ subject.add(from: this_document, to: that_document)
56
+ end
57
+
58
+ it 'should return the edge documents' do
59
+ created_edges = subject.add(from: this_document, to: that_document)
60
+
61
+ expect(created_edges).to eq new_edge
62
+ end
63
+ end
64
+
65
+ context 'removing edges by example' do
66
+ let(:this_document) { instance_double('Ashikawa::Core::Document', id: 'this_document_id') }
67
+ let(:that_document) { instance_double('Ashikawa::Core::Document', id: 'that_document_id') }
68
+ let(:query) { double('Query') }
69
+ let(:aql_string) do
70
+ <<-AQL.gsub(/^[ \t]*/, '')
71
+ FOR e IN @@edge_collection
72
+ FILTER e._from == @from && e._to == @to
73
+ REMOVE e._key IN @@edge_collection
74
+ AQL
75
+ end
76
+ let(:bind_vars) { { :'@edge_collection' => 'relation', :from => 'this_document_id', :to => 'that_document_id' } }
77
+
78
+ before do
79
+ allow(database).to receive(:query).and_return(query)
80
+ end
81
+
82
+ it 'should remove the edges' do
83
+ expect(query).to receive(:execute)
84
+ .with(aql_string, bind_vars: bind_vars)
85
+
86
+ subject.remove(from: this_document, to: that_document)
87
+ end
88
+ end
89
+
90
+ it 'should overwrite #send_request_for_this_collection to use gharial' do
91
+ expect(subject).to receive(:send_request)
92
+ .with('gharial/my_graph/edge/relation/edge_key', {})
93
+
94
+ subject.send(:send_request_for_this_collection, 'edge_key')
95
+ end
96
+
97
+ it 'should overwrite the #build_content_class to create edges with the graph attached' do
98
+ expect(Ashikawa::Core::Edge).to receive(:new)
99
+ .with(database, raw_edge, graph: graph)
100
+ .and_return(new_edge)
101
+
102
+ subject.build_content_class(raw_edge)
103
+ end
104
+ end
105
+ end
@@ -55,6 +55,13 @@ describe Ashikawa::Core::Edge do
55
55
  subject['last_name'] = new_last_name
56
56
  subject.save
57
57
  end
58
+
59
+ it 'should send requests to the edge endpoint' do
60
+ expect(database).to receive(:send_request)
61
+ .with("edge/#{id}", {})
62
+
63
+ subject.send(:send_request_for_document, {})
64
+ end
58
65
  end
59
66
 
60
67
  describe 'initializing edge with additional data' do
@@ -63,5 +70,21 @@ describe Ashikawa::Core::Edge do
63
70
  subject { Ashikawa::Core::Edge.new(database, raw_data, additional_data) }
64
71
 
65
72
  its(['more_info']) { should eq(more_info) }
73
+
74
+ context 'initializing with a graph' do
75
+ let(:graph) { double('Ashikawa::Core::Graph', name: 'my-graph') }
76
+ let(:additional_data_with_graph) { { graph: graph, more_info: more_info } }
77
+ subject { Ashikawa::Core::Edge.new(database, raw_data, additional_data_with_graph) }
78
+
79
+ its(['more_info']) { should eq(more_info) }
80
+ its(:graph) { should eq(graph) }
81
+
82
+ it 'should send requests through the graph module' do
83
+ expect(database).to receive(:send_request)
84
+ .with("gharial/my-graph/edge/#{id}", {})
85
+
86
+ subject.send(:send_request_for_document, {})
87
+ end
88
+ end
66
89
  end
67
90
  end
@@ -1,4 +1,6 @@
1
1
  # -*- encoding : utf-8 -*-
2
+ require 'unit/spec_helper'
3
+
2
4
  require 'ashikawa-core/exceptions/no_collection_provided'
3
5
  require 'ashikawa-core/exceptions/client_error'
4
6
  require 'ashikawa-core/exceptions/client_error/authentication_failed'
@@ -6,7 +8,9 @@ require 'ashikawa-core/exceptions/client_error/bad_syntax'
6
8
  require 'ashikawa-core/exceptions/client_error/resource_not_found'
7
9
  require 'ashikawa-core/exceptions/client_error/resource_not_found/document_not_found'
8
10
  require 'ashikawa-core/exceptions/client_error/resource_not_found/collection_not_found'
11
+ require 'ashikawa-core/exceptions/client_error/resource_not_found/collection_not_in_graph'
9
12
  require 'ashikawa-core/exceptions/client_error/resource_not_found/index_not_found'
13
+ require 'ashikawa-core/exceptions/client_error/resource_not_found/graph_not_found'
10
14
  require 'ashikawa-core/exceptions/server_error'
11
15
  require 'ashikawa-core/exceptions/server_error/json_error'
12
16
 
@@ -48,6 +52,14 @@ describe Ashikawa::Core::IndexNotFoundException do
48
52
  its(:to_s) { should include 'does not exist' }
49
53
  end
50
54
 
55
+ describe Ashikawa::Core::GraphNotFoundException do
56
+ its(:to_s) { should include 'does not exist' }
57
+ end
58
+
59
+ describe Ashikawa::Core::CollectionNotInGraphException do
60
+ its(:to_s) { should include 'not been added to the graph yet' }
61
+ end
62
+
51
63
  describe Ashikawa::Core::ServerError do
52
64
  let(:error_message) { 'The server is misbehaving' }
53
65
  subject { Ashikawa::Core::ServerError.new(error_message) }
@@ -11,6 +11,7 @@ describe Ashikawa::Core::FaradayFactory do
11
11
  before do
12
12
  allow(Faraday).to receive(:new).with(api_string).and_yield(config_block)
13
13
  allow(config_block).to receive(:request).with(:json)
14
+ allow(config_block).to receive(:request).with(:x_arango_version)
14
15
  allow(config_block).to receive(:response).with(:error_response)
15
16
  allow(config_block).to receive(:response).with(:json)
16
17
  allow(config_block).to receive(:adapter).with(Faraday.default_adapter)
@@ -0,0 +1,270 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'unit/spec_helper'
3
+ require 'ashikawa-core/graph'
4
+ require 'ashikawa-core/document'
5
+ require 'ashikawa-core/database'
6
+
7
+ describe Ashikawa::Core::Graph do
8
+ let(:database) { instance_double('Ashikawa::Core::Database') }
9
+ let(:raw_graph) { double('RawGraph').as_null_object }
10
+ let(:edge_definition) do
11
+ {
12
+ 'collection' => 'friends',
13
+ 'from' => %w(ponies),
14
+ 'to' => %w(dragons ponies)
15
+ }
16
+ end
17
+
18
+ def collection_double(name)
19
+ instance_double('Ashikawa::Core::VertexCollection', name: name.to_s)
20
+ end
21
+
22
+ def edge_collection_double(name)
23
+ instance_double('Ashikawa::Core::EdgeCollection', name: name.to_s)
24
+ end
25
+
26
+ context 'an initialized graph' do
27
+ subject { Ashikawa::Core::Graph.new(database, raw_graph) }
28
+
29
+ before do
30
+ allow(raw_graph).to receive(:[]).with('name').and_return('my_graph')
31
+ allow(raw_graph).to receive(:[]).with('_rev').and_return('A113')
32
+ allow(raw_graph).to receive(:fetch).with('orphanCollections').and_return(['orphan'])
33
+ allow(raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([edge_definition])
34
+ end
35
+
36
+ its(:database) { should eq database }
37
+ its(:name) { should eq 'my_graph' }
38
+ its(:revision) { should eq 'A113' }
39
+ its(:edge_definitions) { should eq [edge_definition] }
40
+
41
+ it 'should delegate send_request to the database' do
42
+ expect(database).to receive(:send_request).with('gharial/my_graph')
43
+
44
+ subject.send_request 'gharial/my_graph'
45
+ end
46
+
47
+ it 'should extract the name from the _key if no name was provided' do
48
+ allow(raw_graph).to receive(:[]).with('name').and_return(nil)
49
+ allow(raw_graph).to receive(:[]).with('_key').and_return('my_graph')
50
+ expect(subject.name).to eq 'my_graph'
51
+ end
52
+
53
+ context 'finding neighbors' do
54
+ let(:some_document) { instance_double('Ashikawa::Core::Document', key: 'somekey') }
55
+ let(:query) { double('Query') }
56
+ let(:cursor) { double('Cursor') }
57
+
58
+ before do
59
+ allow(database).to receive(:query).and_return(query)
60
+ end
61
+
62
+ it 'should return the cursor for the query' do
63
+ allow(query).to receive(:execute)
64
+ .and_return(cursor)
65
+
66
+ expect(subject.neighbors(some_document)).to eq cursor
67
+ end
68
+
69
+ it 'should run a neighbors AQL for all edge collections' do
70
+ aql_string = <<-AQL.gsub(/^[ \t]*/, '')
71
+ FOR n IN GRAPH_NEIGHBORS(@graph, { _key:@vertex_key }, {})
72
+ RETURN n.vertex
73
+ AQL
74
+ bind_vars = { graph: 'my_graph', vertex_key: 'somekey' }
75
+
76
+ expect(query).to receive(:execute)
77
+ .with(aql_string, bind_vars: bind_vars)
78
+
79
+ subject.neighbors(some_document)
80
+ end
81
+
82
+ it 'should run a neighbors AQL for a specific edge collection' do
83
+ aql_string = <<-AQL.gsub(/^[ \t]*/, '')
84
+ FOR n IN GRAPH_NEIGHBORS(@graph, { _key:@vertex_key }, {edgeCollectionRestriction: @edge_collection})
85
+ RETURN n.vertex
86
+ AQL
87
+ bind_vars = { edge_collection: ['my-edges'], graph: 'my_graph', vertex_key: 'somekey' }
88
+
89
+ expect(query).to receive(:execute)
90
+ .with(aql_string, bind_vars: bind_vars)
91
+
92
+ subject.neighbors(some_document, edges: ['my-edges'])
93
+ end
94
+ end
95
+
96
+ context 'delete the graph' do
97
+ it 'should delete just the graph' do
98
+ expect(database).to receive(:send_request).with('gharial/my_graph', delete: { dropCollections: false })
99
+
100
+ subject.delete
101
+ end
102
+
103
+ it 'should delete the graph including all collections' do
104
+ expect(database).to receive(:send_request).with('gharial/my_graph', delete: { dropCollections: true })
105
+
106
+ subject.delete(drop_collections: true)
107
+ end
108
+ end
109
+
110
+ context 'vertex collections' do
111
+ let(:raw_vertex_collection) { double('RawVertexCollection') }
112
+
113
+ its(:vertex_collection_names) { should match_array %w(ponies dragons orphan) }
114
+
115
+ it 'should have a list of vertex collections' do
116
+ expected_vertex_collection = [
117
+ collection_double(:ponies),
118
+ collection_double(:orphan),
119
+ collection_double(:dragons)
120
+ ]
121
+ allow(subject).to receive(:vertex_collection).and_return(*expected_vertex_collection)
122
+
123
+ expect(subject.vertex_collections).to match_array expected_vertex_collection
124
+ end
125
+
126
+ it 'should know if a collection has already been added to the list of vertices' do
127
+ allow(subject).to receive(:vertex_collection_names).and_return(['ponies'])
128
+
129
+ expect(subject.has_vertex_collection?('dragons')).to be_falsy
130
+ expect(subject.has_vertex_collection?('ponies')).to be_truthy
131
+ end
132
+
133
+ context 'fetching a single collection' do
134
+ let(:existing_vertex_collection) { instance_double('Ashikawa::Core::VertexCollection') }
135
+
136
+ before do
137
+ allow(database).to receive(:send_request)
138
+ .with('collection/places')
139
+ .and_return(raw_vertex_collection)
140
+
141
+ allow(Ashikawa::Core::VertexCollection).to receive(:new)
142
+ .with(database, raw_vertex_collection, subject)
143
+ .and_return(existing_vertex_collection)
144
+ end
145
+
146
+ it 'should get a single vertex collection' do
147
+ places_collection = subject.vertex_collection 'places'
148
+ expect(places_collection).to eq existing_vertex_collection
149
+ end
150
+ end
151
+
152
+ context 'adding a collection' do
153
+ let(:updated_raw_graph) { double('UpdatedRawGraph') }
154
+ let(:new_vertex_collection) { instance_double('Ashikawa::Core::VertexCollection') }
155
+
156
+ before do
157
+ allow(updated_raw_graph).to receive(:[]).with('name').and_return('my_graph')
158
+ allow(updated_raw_graph).to receive(:[]).with('_rev')
159
+ allow(updated_raw_graph).to receive(:fetch).with('orphanCollections').and_return(['books'])
160
+ allow(updated_raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([edge_definition])
161
+
162
+ allow(database).to receive(:send_request)
163
+ .with('gharial/my_graph/vertex', post: { collection: 'books' })
164
+ .and_return({ 'graph' => updated_raw_graph })
165
+
166
+ allow(database).to receive(:send_request)
167
+ .with('collection/books')
168
+ .and_return(raw_vertex_collection)
169
+
170
+ allow(Ashikawa::Core::VertexCollection).to receive(:new)
171
+ .with(database, raw_vertex_collection, subject)
172
+ .and_return(new_vertex_collection)
173
+ end
174
+
175
+ it 'should add the new collection to the vertex collections of the graph' do
176
+ books_collection = collection_double(:books)
177
+ allow(subject).to receive(:vertex_collection).and_return(books_collection)
178
+
179
+ subject.add_vertex_collection 'books'
180
+
181
+ expect(subject.vertex_collections).to include books_collection
182
+ end
183
+
184
+ it 'should return the newly created collection' do
185
+ expect(subject.add_vertex_collection('books')).to eq new_vertex_collection
186
+ end
187
+ end
188
+ end
189
+
190
+ context 'edge collections' do
191
+ let(:raw_edge_collection) { double('RawEdgeCollection') }
192
+
193
+ its(:edge_collection_names) { should match_array %w(friends) }
194
+
195
+ it 'should have a list of edge collections' do
196
+ expected_edge_collections = [edge_collection_double(:friends)]
197
+ allow(subject).to receive(:edge_collection).and_return(*expected_edge_collections)
198
+
199
+ expect(subject.edge_collections).to match_array expected_edge_collections
200
+ end
201
+
202
+ context 'fetching a single edge collections' do
203
+ let(:existing_edge_collection) { instance_double('Ashikawa::Core::EdgeCollection') }
204
+
205
+ before do
206
+ allow(database).to receive(:send_request)
207
+ .with('collection/friends')
208
+ .and_return(raw_edge_collection)
209
+
210
+ allow(Ashikawa::Core::EdgeCollection).to receive(:new)
211
+ .with(database, raw_edge_collection, subject)
212
+ .and_return(existing_edge_collection)
213
+ end
214
+
215
+ it 'should return a single edge collection' do
216
+ friends_colection = subject.edge_collection :friends
217
+ expect(friends_colection).to eq existing_edge_collection
218
+ end
219
+ end
220
+
221
+ context 'adding a definition' do
222
+ let(:updated_raw_graph) { double('UpdatedRawGraph') }
223
+ let(:new_edge_collection) { instance_double('Ashikawa::Core::EdgeCollection') }
224
+ let(:new_edge_definition) do
225
+ {
226
+ 'collection' => 'authorship',
227
+ 'from' => ['author'],
228
+ 'to' => ['books']
229
+ }
230
+ end
231
+
232
+ before do
233
+ allow(updated_raw_graph).to receive(:[]).with('name').and_return('my_graph')
234
+ allow(updated_raw_graph).to receive(:[]).with('_rev')
235
+ allow(updated_raw_graph).to receive(:fetch).with('orphanCollections').and_return(['orphans'])
236
+ allow(updated_raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([edge_definition])
237
+
238
+ allow(database).to receive(:send_request)
239
+ .with('gharial/my_graph/edge', post: { collection: :authorship, from: [:author], to: [:books] })
240
+ .and_return({ 'graph' => updated_raw_graph })
241
+
242
+ allow(subject).to receive(:edge_collection).and_return(new_edge_collection)
243
+ end
244
+
245
+ it 'should define the name and direction' do
246
+ expect(database).to receive(:send_request)
247
+ .with('gharial/my_graph/edge', post: { collection: :authorship, from: [:author], to: [:books] })
248
+ .and_return({ 'graph' => updated_raw_graph })
249
+
250
+ subject.add_edge_definition(:authorship, from: [:author], to: [:books])
251
+ end
252
+
253
+ it 'should add the definition to the collection edge collections' do
254
+ allow(updated_raw_graph).to receive(:fetch).with('edgeDefinitions').and_return([
255
+ edge_definition,
256
+ new_edge_definition
257
+ ])
258
+
259
+ subject.add_edge_definition(:authorship, from: [:author], to: [:books])
260
+
261
+ expect(subject.edge_collections).to include new_edge_collection
262
+ end
263
+
264
+ it 'should return the edge collection' do
265
+ expect(subject.add_edge_definition(:authorship, from: [:author], to: [:books])).to eq new_edge_collection
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end