ashikawa-core 0.9.0 → 0.10.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +7 -7
  4. data/CHANGELOG.md +25 -0
  5. data/CONTRIBUTING.md +4 -4
  6. data/Gemfile.devtools +32 -16
  7. data/README.md +9 -11
  8. data/Rakefile +3 -0
  9. data/ashikawa-core.gemspec +7 -5
  10. data/config/flay.yml +2 -2
  11. data/config/flog.yml +2 -1
  12. data/config/mutant.yml +14 -1
  13. data/config/reek.yml +9 -4
  14. data/config/rubocop.yml +14 -14
  15. data/lib/ashikawa-core/collection.rb +10 -6
  16. data/lib/ashikawa-core/configuration.rb +10 -5
  17. data/lib/ashikawa-core/connection.rb +30 -21
  18. data/lib/ashikawa-core/cursor.rb +2 -3
  19. data/lib/ashikawa-core/database.rb +12 -35
  20. data/lib/ashikawa-core/document.rb +3 -4
  21. data/lib/ashikawa-core/edge.rb +5 -5
  22. data/lib/ashikawa-core/error_response.rb +108 -0
  23. data/lib/ashikawa-core/index.rb +4 -14
  24. data/lib/ashikawa-core/query.rb +1 -1
  25. data/lib/ashikawa-core/transaction.rb +1 -16
  26. data/lib/ashikawa-core/version.rb +1 -1
  27. data/spec/acceptance/basic_spec.rb +9 -6
  28. data/spec/acceptance/spec_helper.rb +5 -4
  29. data/spec/setup/arangodb.sh +12 -17
  30. data/spec/unit/collection_spec.rb +60 -18
  31. data/spec/unit/configuration_spec.rb +35 -4
  32. data/spec/unit/connection_spec.rb +23 -65
  33. data/spec/unit/cursor_spec.rb +2 -2
  34. data/spec/unit/database_spec.rb +16 -28
  35. data/spec/unit/document_spec.rb +3 -3
  36. data/spec/unit/edge_spec.rb +1 -1
  37. data/spec/unit/index_spec.rb +1 -1
  38. data/spec/unit/query_spec.rb +1 -1
  39. data/spec/unit/spec_helper.rb +3 -2
  40. data/tasks/adjustments.rake +0 -14
  41. metadata +26 -13
  42. data/lib/ashikawa-core/request_preprocessor.rb +0 -50
  43. data/lib/ashikawa-core/response_preprocessor.rb +0 -160
@@ -14,15 +14,16 @@ end
14
14
 
15
15
  require 'ashikawa-core'
16
16
 
17
- port = ENV['ARANGODB_PORT'] || 8529
18
- username = ENV['ARANGODB_USERNAME'] || 'root'
19
- password = ENV['ARANGODB_PASSWORD'] || ''
17
+ port = ENV.fetch('ARANGODB_PORT', 8529)
18
+ username = ENV.fetch('ARANGODB_USERNAME', 'root')
19
+ password = ENV.fetch('ARANGODB_PASSWORD', '')
20
+ authentification_enabled = ENV['ARANGODB_DISABLE_AUTHENTIFICATION'] == 'false'
20
21
 
21
22
  # The database instance to use for all specs
22
23
  DATABASE = Ashikawa::Core::Database.new do |config|
23
24
  config.url = "http://localhost:#{port}"
24
25
 
25
- unless ENV['ARANGODB_DISABLE_AUTHENTIFICATION']
26
+ if authentification_enabled
26
27
  config.username = username
27
28
  config.password = password
28
29
  end
@@ -3,15 +3,15 @@
3
3
  DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4
4
  cd $DIR
5
5
 
6
- # VERSION=1.4.devel
7
6
  NAME=ArangoDB-$VERSION
8
7
 
9
8
  if [ ! -d "$DIR/$NAME" ]; then
10
9
  # download ArangoDB
11
- echo "wget http://www.arangodb.org/travisCI/$NAME.tar.gz"
12
- wget http://www.arangodb.org/travisCI/$NAME.tar.gz
10
+ echo "wget http://www.arangodb.org/repositories/travisCI/$NAME.tar.gz"
11
+ wget http://www.arangodb.org/repositories/travisCI/$NAME.tar.gz
13
12
  echo "tar zxf $NAME.tar.gz"
14
13
  tar zvxf $NAME.tar.gz
14
+ mv `find . -type d -name "ArangoDB-*"` $NAME
15
15
  fi
16
16
 
17
17
  ARCH=$(arch)
@@ -19,29 +19,24 @@ PID=$(echo $PPID)
19
19
  TMP_DIR="/tmp/arangodb.$PID"
20
20
  PID_FILE="/tmp/arangodb.$PID.pid"
21
21
  ARANGODB_DIR="$DIR/$NAME"
22
-
23
- ARANGOD="${ARANGODB_DIR}/bin/arangod"
24
- if [ "$ARCH" == "x86_64" ]; then
25
- ARANGOD="${ARANGOD}_x86_64"
26
- fi
22
+ ARANGOD="${ARANGODB_DIR}/bin/arangod_x86_64"
27
23
 
28
24
  # create database directory
29
25
  mkdir ${TMP_DIR}
30
26
 
31
- echo "Starting arangodb '${ARANGOD}'"
27
+ echo "Starting ArangoDB '${ARANGOD}'"
32
28
 
33
29
  ${ARANGOD} \
34
- --database.directory ${TMP_DIR} \
35
- --configuration none \
30
+ --database.directory ${TMP_DIR} \
31
+ --configuration none \
36
32
  --server.endpoint tcp://127.0.0.1:8529 \
33
+ --javascript.app-path ${ARANGODB_DIR}/js/apps \
37
34
  --javascript.startup-directory ${ARANGODB_DIR}/js \
38
- --server.admin-directory ${ARANGODB_DIR}/html/admin \
39
35
  --javascript.modules-path ${ARANGODB_DIR}/js/server/modules:${ARANGODB_DIR}/js/common/modules:${ARANGODB_DIR}/js/node \
40
36
  --javascript.package-path ${ARANGODB_DIR}/js/npm:${ARANGODB_DIR}/js/common/test-data/modules \
41
- --javascript.action-directory ${ARANGODB_DIR}/js/actions \
42
- --database.maximal-journal-size 1048576 \
43
- --server.disable-admin-interface ${ARANGODB_DISABLE_AUTHENTIFICATION} \
44
- --server.disable-authentication true \
37
+ --javascript.action-directory ${ARANGODB_DIR}/js/actions \
38
+ --database.maximal-journal-size 1048576 \
39
+ --server.disable-authentication ${ARANGODB_DISABLE_AUTHENTIFICATION} \
45
40
  --javascript.gc-interval 1 &
46
41
 
47
42
  sleep 2
@@ -56,7 +51,7 @@ if [ "x$process" == "x" ]; then
56
51
  fi
57
52
 
58
53
  echo "Waiting until ArangoDB is ready on port 8529"
59
- while [[ -z `curl -s 'http://127.0.0.1:8529/_api/version' ` ]] ; do
54
+ while [[ -z `curl --basic --user 'root:' -s 'http://127.0.0.1:8529/_api/version' ` ]] ; do
60
55
  echo -n "."
61
56
  sleep 2s
62
57
  done
@@ -4,7 +4,16 @@ require 'ashikawa-core/collection'
4
4
 
5
5
  describe Ashikawa::Core::Collection do
6
6
  let(:database) { double }
7
- let(:raw_document_collection) { server_response('collections/60768679') }
7
+ let(:raw_document_collection) do
8
+ {
9
+ 'id' => '60768679',
10
+ 'name' => 'example_1',
11
+ 'status' => 3,
12
+ 'type' => 2,
13
+ 'error' => false,
14
+ 'code' => 200
15
+ }
16
+ end
8
17
  let(:raw_edge_collection) do
9
18
  {
10
19
  'id' => '60768679',
@@ -223,29 +232,62 @@ describe Ashikawa::Core::Collection do
223
232
 
224
233
  its(:content_type) { should be(:document) }
225
234
 
226
- it 'should receive a document by ID via fetch' do
227
- expect(database).to receive(:send_request)
228
- .with('document/60768679/333', {})
229
- .and_return(double)
230
- expect(Ashikawa::Core::Document).to receive(:new)
235
+ context 'when using the key' do
236
+ let(:key) { 333 }
231
237
 
232
- subject.fetch(333)
233
- end
238
+ it 'should receive a document by ID via fetch' do
239
+ expect(database).to receive(:send_request)
240
+ .with('document/60768679/333', {})
241
+ .and_return(double)
242
+ expect(Ashikawa::Core::Document).to receive(:new)
234
243
 
235
- it 'should receive a document by ID via []' do
236
- expect(database).to receive(:send_request)
237
- .with('document/60768679/333', {})
238
- .and_return(double)
239
- expect(Ashikawa::Core::Document).to receive(:new)
244
+ subject.fetch(key)
245
+ end
240
246
 
241
- subject[333]
247
+ it 'should receive a document by ID via []' do
248
+ expect(database).to receive(:send_request)
249
+ .with('document/60768679/333', {})
250
+ .and_return(double)
251
+ expect(Ashikawa::Core::Document).to receive(:new)
252
+
253
+ subject[key]
254
+ end
255
+
256
+ it 'should replace a document by ID' do
257
+ expect(database).to receive(:send_request)
258
+ .with('document/60768679/333', put: { 'name' => value })
259
+
260
+ subject.replace(key, { 'name' => value })
261
+ end
242
262
  end
243
263
 
244
- it 'should replace a document by ID' do
245
- expect(database).to receive(:send_request)
246
- .with('document/60768679/333', put: { 'name' => value })
264
+ context 'when using the ID' do
265
+ let(:id) { '60768679/333' }
266
+
267
+ it 'should receive a document by ID via fetch' do
268
+ expect(database).to receive(:send_request)
269
+ .with('document/60768679/333', {})
270
+ .and_return(double)
271
+ expect(Ashikawa::Core::Document).to receive(:new)
247
272
 
248
- subject.replace(333, { 'name' => value })
273
+ subject.fetch(id)
274
+ end
275
+
276
+ it 'should receive a document by ID via []' do
277
+ expect(database).to receive(:send_request)
278
+ .with('document/60768679/333', {})
279
+ .and_return(double)
280
+ expect(Ashikawa::Core::Document).to receive(:new)
281
+
282
+ subject[id]
283
+ end
284
+
285
+ it 'should replace a document by ID' do
286
+ expect(database).to receive(:send_request)
287
+ .with('document/60768679/333', put: { 'name' => value })
288
+
289
+ subject.replace(id, { 'name' => value })
290
+ end
249
291
  end
250
292
 
251
293
  it 'should create a new document' do
@@ -20,12 +20,12 @@ describe Ashikawa::Core::Configuration do
20
20
  end.to raise_error(ArgumentError, /either an url or a connection/)
21
21
  end
22
22
 
23
- describe 'provided with connection' do
23
+ context 'provided with connection' do
24
24
  before { subject.connection = connection }
25
25
  its(:connection) { should be connection }
26
26
  end
27
27
 
28
- describe 'provided with url, logger and adapter' do
28
+ context 'provided with url, logger and adapter' do
29
29
  before do
30
30
  subject.url = url
31
31
  subject.logger = logger
@@ -44,6 +44,23 @@ describe Ashikawa::Core::Configuration do
44
44
  end
45
45
  end
46
46
 
47
+ context 'provided with url' do
48
+ before do
49
+ subject.url = url
50
+ end
51
+
52
+ its(:url) { should be url }
53
+ its(:logger) { should be nil }
54
+ its(:adapter) { should be nil }
55
+
56
+ it 'should construct a connection' do
57
+ expect(Ashikawa::Core::Connection).to receive(:new)
58
+ .with(url, {})
59
+ .and_return(connection)
60
+ expect(subject.connection).to be connection
61
+ end
62
+ end
63
+
47
64
  describe 'set up authentication' do
48
65
  before do
49
66
  subject.url = url
@@ -51,14 +68,28 @@ describe Ashikawa::Core::Configuration do
51
68
  .and_return(connection)
52
69
  end
53
70
 
54
- it 'should setup authentication' do
71
+ it 'should setup authentication when username and password were provided' do
55
72
  expect(connection).to receive(:authenticate_with)
56
- .with({ username: username, password: password })
73
+ .with(username, password)
57
74
  .and_return(connection)
58
75
 
59
76
  subject.username = username
60
77
  subject.password = password
61
78
  subject.connection
62
79
  end
80
+
81
+ it 'should not setup authentication when only username was provided' do
82
+ expect(connection).to_not receive(:authenticate_with)
83
+
84
+ subject.username = username
85
+ subject.connection
86
+ end
87
+
88
+ it 'should not setup authentication when only password was provided' do
89
+ expect(connection).to_not receive(:authenticate_with)
90
+
91
+ subject.password = password
92
+ subject.connection
93
+ end
63
94
  end
64
95
  end
@@ -46,26 +46,7 @@ describe Ashikawa::Core::Connection do
46
46
  [200, response_headers, JSON.generate({ 'name' => 'dude' })]
47
47
  end
48
48
 
49
- subject.send_request 'my/path', delete: { }
50
- request_stub.verify_stubbed_calls
51
- end
52
-
53
- it 'should write JSON request' do
54
- request_stub.post('/_api/my/path') do |req|
55
- expect(req[:body]).to eq('{"test":1}')
56
- [200, response_headers, JSON.generate({ 'name' => 'dude' })]
57
- end
58
-
59
- subject.send_request('my/path', post: { 'test' => 1 })
60
- request_stub.verify_stubbed_calls
61
- end
62
-
63
- it 'should parse JSON response' do
64
- request_stub.get('/_api/my/path') do
65
- [200, response_headers, '{"name":"dude"}']
66
- end
67
-
68
- expect(subject.send_request('my/path')).to eq({ 'name' => 'dude' })
49
+ subject.send_request 'my/path', delete: {}
69
50
  request_stub.verify_stubbed_calls
70
51
  end
71
52
 
@@ -75,24 +56,10 @@ describe Ashikawa::Core::Connection do
75
56
  end
76
57
 
77
58
  it 'should tell if authentication is enabled' do
78
- subject.authenticate_with(username: 'testuser', password: 'testpassword')
59
+ subject.authenticate_with('testuser', 'testpassword')
79
60
  expect(subject.authentication?).to be_true
80
61
  end
81
62
 
82
- it 'should only accept username & password pairs' do
83
- expect do
84
- subject.authenticate_with(username: 'kitty')
85
- end.to raise_error(ArgumentError)
86
-
87
- expect do
88
- subject.authenticate_with(password: 'cheezburger?')
89
- end.to raise_error(ArgumentError)
90
- end
91
-
92
- it 'should allow chaining' do
93
- expect(subject.authenticate_with(username: 'a', password: 'b')).to eq(subject)
94
- end
95
-
96
63
  it 'should send the authentication data with every GET request' do
97
64
  pending 'Find out how to check for basic auth via Faraday Stubs'
98
65
 
@@ -216,43 +183,34 @@ describe Ashikawa::Core::Connection do
216
183
 
217
184
  request_stub.verify_stubbed_calls
218
185
  end
219
-
220
- it 'should raise an error if the content type of the response is not JSON' do
221
- request_stub.get('/_api/document/4590/333') do
222
- [200, { 'content-type' => 'text/html; charset=utf-8' }, '']
223
- end
224
-
225
- expect { subject.send_request 'document/4590/333' }.to raise_error(Ashikawa::Core::JsonError)
226
-
227
- request_stub.verify_stubbed_calls
228
- end
229
186
  end
230
187
 
231
- describe 'logging' do
232
- let(:request_stub) { Faraday::Adapter::Test::Stubs.new }
233
- let(:logger) { double }
234
- subject do
235
- Ashikawa::Core::Connection.new(ARANGO_HOST, adapter: [:test, request_stub], logger: logger)
236
- end
188
+ describe 'initializing Faraday' do
189
+ subject { Ashikawa::Core::Connection }
190
+ let(:adapter) { double('Adapter') }
191
+ let(:logger) { double('Logger') }
192
+ let(:blocky) { double('Block') }
237
193
 
238
- it 'should log a get request' do
239
- request_stub.get('/_api/test') do
240
- [200, response_headers, JSON.generate({ a: 1 })]
241
- end
242
- expect(logger).to receive(:info).with("GET #{ARANGO_HOST}/_api/test ")
243
- expect(logger).to receive(:info).with('200 {"a":1}')
194
+ it 'should initalize with specific logger and adapter' do
195
+ expect(Faraday).to receive(:new).with("#{ARANGO_HOST}/_api").and_yield(blocky)
196
+ expect(blocky).to receive(:request).with(:json)
197
+ expect(blocky).to receive(:response).with(:logger, logger)
198
+ expect(blocky).to receive(:response).with(:error_response)
199
+ expect(blocky).to receive(:response).with(:json)
200
+ expect(blocky).to receive(:adapter).with(adapter)
244
201
 
245
- subject.send_request('test')
202
+ subject.new(ARANGO_HOST, adapter: adapter, logger: logger)
246
203
  end
247
204
 
248
- it 'should log a post request' do
249
- request_stub.post('/_api/test') do
250
- [201, response_headers, JSON.generate({ b: 2 })]
251
- end
252
- expect(logger).to receive(:info).with("POST #{ARANGO_HOST}/_api/test {:a=>2}")
253
- expect(logger).to receive(:info).with('201 {"b":2}')
205
+ it 'should initialize with defaults when no specific logger and adapter was given' do
206
+ expect(Faraday).to receive(:new).with("#{ARANGO_HOST}/_api").and_yield(blocky)
207
+ expect(blocky).to receive(:request).with(:json)
208
+ expect(blocky).to receive(:response).with(:logger, NullLogger.instance)
209
+ expect(blocky).to receive(:response).with(:error_response)
210
+ expect(blocky).to receive(:response).with(:json)
211
+ expect(blocky).to receive(:adapter).with(Faraday.default_adapter)
254
212
 
255
- subject.send_request('test', post: { a: 2 })
213
+ subject.new(ARANGO_HOST)
256
214
  end
257
215
  end
258
216
  end
@@ -45,7 +45,7 @@ describe Ashikawa::Core::Cursor do
45
45
  expect(Ashikawa::Core::Document).to receive(:new)
46
46
  .exactly(5).times
47
47
 
48
- subject.each { }
48
+ subject.each {}
49
49
  end
50
50
 
51
51
  it 'should return the raw string when the response consists of strings' do
@@ -112,7 +112,7 @@ describe Ashikawa::Core::Cursor do
112
112
  expect(Ashikawa::Core::Edge).to receive(:new)
113
113
  .exactly(2).times
114
114
 
115
- subject.each { }
115
+ subject.each {}
116
116
  end
117
117
  end
118
118
 
@@ -16,6 +16,8 @@ describe Ashikawa::Core::Database do
16
16
  let(:logger) { double }
17
17
  let(:adapter) { double }
18
18
  let(:configuration) { double }
19
+ let(:raw_collection) { double }
20
+ let(:collection) { double }
19
21
 
20
22
  it 'should initialize with a configuration object' do
21
23
  expect(Ashikawa::Core::Configuration).to receive(:new)
@@ -33,19 +35,12 @@ describe Ashikawa::Core::Database do
33
35
 
34
36
  it 'should create a query' do
35
37
  expect(Ashikawa::Core::Query).to receive(:new)
36
- .exactly(1).times
38
+ .once
37
39
  .with(subject)
38
40
 
39
41
  subject.query
40
42
  end
41
43
 
42
- it 'should delegate authentication to the connection' do
43
- expect(connection).to receive(:authenticate_with)
44
- .with({ username: 'user', password: 'password' })
45
-
46
- subject.authenticate_with username: 'user', password: 'password'
47
- end
48
-
49
44
  it 'should fetch all available non-system collections' do
50
45
  expect(connection).to receive(:send_request)
51
46
  .with('collection')
@@ -73,10 +68,10 @@ describe Ashikawa::Core::Database do
73
68
  it 'should create a non volatile collection by default' do
74
69
  expect(connection).to receive(:send_request)
75
70
  .with('collection', post: { name: 'volatile_collection' })
76
- .and_return { server_response('collections/60768679') }
71
+ .and_return { raw_collection }
77
72
 
78
73
  expect(Ashikawa::Core::Collection).to receive(:new)
79
- .with(subject, server_response('collections/60768679'))
74
+ .with(subject, raw_collection)
80
75
 
81
76
  subject.create_collection('volatile_collection')
82
77
  end
@@ -84,10 +79,10 @@ describe Ashikawa::Core::Database do
84
79
  it 'should create a volatile collection when asked' do
85
80
  expect(connection).to receive(:send_request)
86
81
  .with('collection', post: { name: 'volatile_collection', isVolatile: true })
87
- .and_return { |path| server_response('collections/60768679') }
82
+ .and_return { |path| raw_collection }
88
83
 
89
84
  expect(Ashikawa::Core::Collection).to receive(:new)
90
- .with(subject, server_response('collections/60768679'))
85
+ .with(subject, raw_collection)
91
86
 
92
87
  subject.create_collection('volatile_collection', is_volatile: true)
93
88
  end
@@ -117,10 +112,10 @@ describe Ashikawa::Core::Database do
117
112
  it 'should create an edge collection when asked' do
118
113
  expect(connection).to receive(:send_request)
119
114
  .with('collection', post: { name: 'volatile_collection', type: 3 })
120
- .and_return { |path| server_response('collections/60768679') }
115
+ .and_return { |path| raw_collection }
121
116
 
122
117
  expect(Ashikawa::Core::Collection).to receive(:new)
123
- .with(subject, server_response('collections/60768679'))
118
+ .with(subject, raw_collection)
124
119
 
125
120
  subject.create_collection('volatile_collection', content_type: :edge)
126
121
  end
@@ -128,10 +123,10 @@ describe Ashikawa::Core::Database do
128
123
  it 'should fetch a single collection if it exists' do
129
124
  expect(connection).to receive(:send_request)
130
125
  .with('collection/60768679')
131
- .and_return { |path| server_response('collections/60768679') }
126
+ .and_return { |path| raw_collection }
132
127
 
133
128
  expect(Ashikawa::Core::Collection).to receive(:new)
134
- .with(subject, server_response('collections/60768679'))
129
+ .with(subject, raw_collection)
135
130
 
136
131
  subject.collection(60_768_679)
137
132
  end
@@ -139,26 +134,19 @@ describe Ashikawa::Core::Database do
139
134
  it 'should fetch a single collection with the array syntax' do
140
135
  expect(connection).to receive(:send_request)
141
136
  .with('collection/60768679')
142
- .and_return { |path| server_response('collections/60768679') }
137
+ .and_return { |path| raw_collection }
143
138
 
144
139
  expect(Ashikawa::Core::Collection).to receive(:new)
145
- .with(subject, server_response('collections/60768679'))
140
+ .with(subject, raw_collection)
146
141
 
147
142
  subject[60_768_679]
148
143
  end
149
144
 
150
145
  it "should create a single collection if it doesn't exist" do
151
- allow(connection).to receive :send_request do |path, method|
152
- method ||= {}
153
- if method.key? :post
154
- server_response('collections/60768679')
155
- else
156
- raise Ashikawa::Core::CollectionNotFoundException
157
- end
146
+ expect(connection).to receive(:send_request).with('collection/new_collection') do
147
+ raise Ashikawa::Core::CollectionNotFoundException
158
148
  end
159
- expect(connection).to receive(:send_request).with('collection/new_collection')
160
- expect(connection).to receive(:send_request).with('collection', post: { name: 'new_collection' })
161
- expect(Ashikawa::Core::Collection).to receive(:new).with(subject, server_response('collections/60768679'))
149
+ expect(subject).to receive(:create_collection).with('new_collection').and_return(collection)
162
150
 
163
151
  subject['new_collection']
164
152
  end