ashikawa-core 0.9.0 → 0.10.0

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