rdropbox 1.0.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.
- data/.document +5 -0
- data/.gitignore +24 -0
- data/LICENSE +20 -0
- data/README.rdoc +84 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/dropbox.gemspec +87 -0
- data/lib/dropbox/api.rb +530 -0
- data/lib/dropbox/entry.rb +96 -0
- data/lib/dropbox/event.rb +109 -0
- data/lib/dropbox/memoization.rb +98 -0
- data/lib/dropbox/revision.rb +197 -0
- data/lib/dropbox/session.rb +160 -0
- data/lib/dropbox.rb +43 -0
- data/lib/extensions/array.rb +9 -0
- data/lib/extensions/hash.rb +61 -0
- data/lib/extensions/module.rb +22 -0
- data/lib/extensions/object.rb +5 -0
- data/lib/extensions/string.rb +9 -0
- data/lib/extensions/to_bool.rb +17 -0
- data/spec/dropbox/api_spec.rb +778 -0
- data/spec/dropbox/entry_spec.rb +144 -0
- data/spec/dropbox/event_spec.rb +122 -0
- data/spec/dropbox/revision_spec.rb +367 -0
- data/spec/dropbox/session_spec.rb +148 -0
- data/spec/dropbox_spec.rb +57 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- metadata +150 -0
@@ -0,0 +1,778 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
def url_args(url)
|
4
|
+
return {} unless url.include?('?')
|
5
|
+
_, back = url.split('?')
|
6
|
+
return {} unless back
|
7
|
+
back.split('&').map { |comp| comp.split('=') }.to_hash
|
8
|
+
end
|
9
|
+
|
10
|
+
def should_receive_api_method_with_arguments(object, method, api_method, arguments, response, path=nil, root=nil)
|
11
|
+
object.should_receive(method).once do |url|
|
12
|
+
front = url.split('?').first
|
13
|
+
front.should eql("#{Dropbox::ALTERNATE_HOSTS[api_method] || Dropbox::HOST}/#{Dropbox::VERSION}/#{api_method}#{'/' + root if root}#{'/' + path if path}")
|
14
|
+
|
15
|
+
query_params = url_args(url)
|
16
|
+
query_params.each { |key, val| val.should eql(arguments[key.to_sym]) }
|
17
|
+
arguments.each { |key, _| query_params.should include(key.to_s) }
|
18
|
+
response
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def stub_for_upload_testing
|
23
|
+
@consumer_mock.stub!(:key).and_return("consumer key")
|
24
|
+
@consumer_mock.stub!(:secret).and_return("consumer secret")
|
25
|
+
@consumer_mock.stub!(:sign!).and_return { |req, _| req.stub!(:to_hash).and_return('authorization' => ["Oauth", "test"]) }
|
26
|
+
|
27
|
+
@token_mock.stub!(:token).and_return("access token")
|
28
|
+
@token_mock.stub!(:secret).and_return("access secret")
|
29
|
+
|
30
|
+
@response.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(true)
|
31
|
+
@response.stub!(:body).and_return('{"test":"val"}')
|
32
|
+
|
33
|
+
Net::HTTP.stub!(:start).and_return(@response)
|
34
|
+
end
|
35
|
+
|
36
|
+
def response_acts_as(subclass)
|
37
|
+
@response.stub(:kind_of?).and_return(false)
|
38
|
+
@response.stub(:kind_of?).with(subclass).and_return(true) if subclass
|
39
|
+
end
|
40
|
+
|
41
|
+
describe Dropbox::API do
|
42
|
+
before :each do
|
43
|
+
@consumer_mock = mock("OAuth::Consumer")
|
44
|
+
token_mock = mock("OAuth::RequestToken")
|
45
|
+
@token_mock = mock("OAuth::AccessToken")
|
46
|
+
token_mock.stub!(:get_access_token).and_return(@token_mock)
|
47
|
+
@consumer_mock.stub!(:get_request_token).and_return(token_mock)
|
48
|
+
OAuth::Consumer.stub!(:new).and_return(@consumer_mock)
|
49
|
+
|
50
|
+
@session = Dropbox::Session.new('foo', 'bar')
|
51
|
+
@session.authorize
|
52
|
+
|
53
|
+
@response = mock('Net::HTTPResponse')
|
54
|
+
@response.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(true)
|
55
|
+
@response.stub!(:code).and_return(200)
|
56
|
+
@response.stub!(:body).and_return("response body")
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#account" do
|
60
|
+
it "should call the /account/info API method" do
|
61
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
62
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'account/info', {}, @response
|
63
|
+
@session.account
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should convert the result into a struct" do
|
67
|
+
@response.stub!(:body).and_return( { :foo => :bar, :baz => { :hey => :you } }.to_json)
|
68
|
+
@token_mock.stub!(:get).and_return(@response)
|
69
|
+
result = @session.account
|
70
|
+
result.foo.should eql('bar')
|
71
|
+
result.baz.hey.should eql('you')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#download" do
|
76
|
+
it "should call the files API method" do
|
77
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'files', {}, @response, 'path/to/file', 'sandbox'
|
78
|
+
@session.download "path/to/file"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should strip a leading slash" do
|
82
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'files', {}, @response, 'path/to/file', 'sandbox'
|
83
|
+
@session.download "/path/to/file"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return the body of the response" do
|
87
|
+
@token_mock.stub!(:get).and_return(@response)
|
88
|
+
@session.download("path/to/file").should eql("response body")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should check the path" do
|
92
|
+
path = "test/path"
|
93
|
+
Dropbox.should_receive(:check_path).once.with(path).and_return(path)
|
94
|
+
@token_mock.stub!(:get).and_return(@response)
|
95
|
+
|
96
|
+
@session.download(path)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#copy" do
|
101
|
+
before :each do
|
102
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should call the fileops/copy API method" do
|
106
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/copy', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
107
|
+
@session.copy 'source/file', 'dest/file'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return the metadata as a struct" do
|
111
|
+
@response.stub!(:body).and_return( { :foo => :bar, :baz => { :hey => :you } }.to_json)
|
112
|
+
@token_mock.stub!(:post).and_return(@response)
|
113
|
+
|
114
|
+
result = @session.copy('a', 'b')
|
115
|
+
result.foo.should eql('bar')
|
116
|
+
result.baz.hey.should eql('you')
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should strip a leading slash from source" do
|
120
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/copy', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
121
|
+
@session.copy '/source/file', 'dest/file'
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should strip a leading slash from target" do
|
125
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/copy', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
126
|
+
@session.copy 'source/file', '/dest/file'
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should set the target file name to the source file name if the target is a directory path" do
|
130
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/copy', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
131
|
+
@session.copy 'source/file', 'dest/'
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should re-raise 404's as FileNotFoundErrors" do
|
135
|
+
response_acts_as Net::HTTPNotFound
|
136
|
+
@token_mock.stub!(:post).and_return(@response)
|
137
|
+
|
138
|
+
lambda { @session.copy('a', 'b') }.should raise_error(Dropbox::FileNotFoundError)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should re-raise 403's as FileExistsErrors" do
|
142
|
+
response_acts_as Net::HTTPForbidden
|
143
|
+
@token_mock.stub!(:post).and_return(@response)
|
144
|
+
|
145
|
+
lambda { @session.copy('a', 'b') }.should raise_error(Dropbox::FileExistsError)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should raise other errors unmodified" do
|
149
|
+
@response.stub(:kind_of?).and_return(false)
|
150
|
+
@token_mock.stub!(:post).and_return(@response)
|
151
|
+
|
152
|
+
lambda { @session.copy('a', 'b') }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should check the source and destination paths" do
|
156
|
+
source_path = "source/path"
|
157
|
+
dest_path = "dest/path"
|
158
|
+
Dropbox.should_receive(:check_path).once.with(source_path).and_return(source_path)
|
159
|
+
Dropbox.should_receive(:check_path).once.with(dest_path).and_return(dest_path)
|
160
|
+
@token_mock.stub!(:post).and_return(@response)
|
161
|
+
|
162
|
+
@session.copy(source_path, dest_path)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "#move" do
|
167
|
+
before :each do
|
168
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should call the fileops/move API method" do
|
172
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/move', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
173
|
+
@session.move 'source/file', 'dest/file'
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return the metadata as a struct" do
|
177
|
+
@response.stub!(:body).and_return( { :foo => :bar, :baz => { :hey => :you } }.to_json)
|
178
|
+
@token_mock.stub!(:post).and_return(@response)
|
179
|
+
|
180
|
+
result = @session.move('a', 'b')
|
181
|
+
result.foo.should eql('bar')
|
182
|
+
result.baz.hey.should eql('you')
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should strip a leading slash from source" do
|
186
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/move', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
187
|
+
@session.move '/source/file', 'dest/file'
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should strip a leading slash from target" do
|
191
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/move', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
192
|
+
@session.move 'source/file', '/dest/file'
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should set the target file name to the source file name if the target is a directory path" do
|
196
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/move', { :from_path => 'source%2Ffile', :to_path => 'dest%2Ffile', :root => 'sandbox' }, @response
|
197
|
+
@session.move 'source/file', 'dest/'
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should re-raise 404's as FileNotFoundErrors" do
|
201
|
+
response_acts_as Net::HTTPNotFound
|
202
|
+
@token_mock.stub!(:post).and_return(@response)
|
203
|
+
|
204
|
+
lambda { @session.move('a', 'b') }.should raise_error(Dropbox::FileNotFoundError)
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should re-raise 403's as FileExistsErrors" do
|
208
|
+
response_acts_as Net::HTTPForbidden
|
209
|
+
@token_mock.stub!(:post).and_return(@response)
|
210
|
+
|
211
|
+
lambda { @session.move('a', 'b') }.should raise_error(Dropbox::FileExistsError)
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should raise other errors unmodified" do
|
215
|
+
response_acts_as nil
|
216
|
+
@token_mock.stub!(:post).and_return(@response)
|
217
|
+
|
218
|
+
lambda { @session.move('a', 'b') }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should check the source and destination paths" do
|
222
|
+
source_path = "source/path"
|
223
|
+
dest_path = "dest/path"
|
224
|
+
Dropbox.should_receive(:check_path).once.with(source_path).and_return(source_path)
|
225
|
+
Dropbox.should_receive(:check_path).once.with(dest_path).and_return(dest_path)
|
226
|
+
@token_mock.stub!(:post).and_return(@response)
|
227
|
+
|
228
|
+
@session.move(source_path, dest_path)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "#rename" do
|
233
|
+
it "should raise an error if the new name has a slash in it" do
|
234
|
+
lambda { @session.rename 'file', 'new/name' }.should raise_error(ArgumentError)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should call move with the appropriate path and return the result of the call" do
|
238
|
+
@session.should_receive(:move).once.with('old/path/to/file', 'old/path/to/new_file', :mode => :sandbox).and_return(@response)
|
239
|
+
@session.rename('old/path/to/file', 'new_file', :mode => :sandbox).should eql(@response)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "#create_folder" do
|
244
|
+
before :each do
|
245
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should call the fileops/create_folder API method" do
|
249
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/create_folder', { :path => 'new%2Ffolder', :root => 'sandbox' }, @response
|
250
|
+
@session.create_folder 'new/folder'
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should return the metadata as a struct" do
|
254
|
+
@response.stub!(:body).and_return( { :foo => :bar, :baz => { :hey => :you } }.to_json)
|
255
|
+
@token_mock.stub!(:post).and_return(@response)
|
256
|
+
|
257
|
+
result = @session.create_folder('a')
|
258
|
+
result.foo.should eql('bar')
|
259
|
+
result.baz.hey.should eql('you')
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should strip a leading slash from the path" do
|
263
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/create_folder', { :path => 'new%2Ffolder', :root => 'sandbox' }, @response
|
264
|
+
@session.create_folder '/new/folder'
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should strip a trailing slash from the path" do
|
268
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/create_folder', { :path => 'new%2Ffolder', :root => 'sandbox' }, @response
|
269
|
+
@session.create_folder 'new/folder/'
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should re-raise 403's as FileExistsErrors" do
|
273
|
+
response_acts_as Net::HTTPForbidden
|
274
|
+
@token_mock.stub!(:post).and_return(@response)
|
275
|
+
|
276
|
+
lambda { @session.create_folder('a') }.should raise_error(Dropbox::FileExistsError)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should raise other errors unmodified" do
|
280
|
+
response_acts_as nil
|
281
|
+
@token_mock.stub!(:post).and_return(@response)
|
282
|
+
|
283
|
+
lambda { @session.create_folder('a') }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should check the path" do
|
287
|
+
path = "source/path"
|
288
|
+
Dropbox.should_receive(:check_path).once.with(path).and_return(path)
|
289
|
+
@token_mock.stub!(:post).and_return(@response)
|
290
|
+
|
291
|
+
@session.create_folder(path)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
describe "#delete" do
|
296
|
+
it "should call the API method fileops/delete" do
|
297
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/delete', { :path => 'some%2Ffile', :root => 'sandbox' }, @response
|
298
|
+
@session.delete 'some/file'
|
299
|
+
end
|
300
|
+
|
301
|
+
it "should return true" do
|
302
|
+
@token_mock.stub!(:post).and_return(@response)
|
303
|
+
@session.delete('some/file').should be_true
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should strip a leading slash from the path" do
|
307
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/delete', { :path => 'some%2Ffile', :root => 'sandbox' }, @response
|
308
|
+
@session.delete '/some/file'
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should strip a trailing slash from the path" do
|
312
|
+
should_receive_api_method_with_arguments @token_mock, :post, 'fileops/delete', { :path => 'some%2Ffile', :root => 'sandbox' }, @response
|
313
|
+
@session.delete 'some/file/'
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should re-raise 404's as FileNotFoundErrors" do
|
317
|
+
response_acts_as Net::HTTPNotFound
|
318
|
+
@token_mock.stub!(:post).and_return(@response)
|
319
|
+
|
320
|
+
lambda { @session.delete('a') }.should raise_error(Dropbox::FileNotFoundError)
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should raise other errors unmodified" do
|
324
|
+
response_acts_as nil
|
325
|
+
@token_mock.stub!(:post).and_return(@response)
|
326
|
+
|
327
|
+
lambda { @session.delete('a') }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
328
|
+
end
|
329
|
+
|
330
|
+
it "should check the path" do
|
331
|
+
path = "source/path"
|
332
|
+
Dropbox.should_receive(:check_path).once.with(path).and_return(path)
|
333
|
+
@token_mock.stub!(:post).and_return(@response)
|
334
|
+
|
335
|
+
@session.delete(path)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "#link" do
|
340
|
+
before :each do
|
341
|
+
@response.stub!(:code).and_return(304)
|
342
|
+
response_acts_as Net::HTTPFound
|
343
|
+
@response.stub!(:[]).and_return("new location")
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should call the API method links" do
|
347
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'links', {}, @response, 'some/file', 'sandbox'
|
348
|
+
@session.link 'some/file'
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should strip a leading slash" do
|
352
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'links', {}, @response, 'some/file', 'sandbox'
|
353
|
+
@session.link '/some/file'
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should rescue 304's and return the Location header" do
|
357
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'links', {}, @response, 'some/file', 'sandbox'
|
358
|
+
lambda { @session.link('some/file').should eql("new location") }.should_not raise_error
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should re-raise other errors unmodified" do
|
362
|
+
response_acts_as nil
|
363
|
+
@token_mock.stub!(:get).and_return(@response)
|
364
|
+
lambda { @session.link('a') }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should check the path" do
|
368
|
+
path = "source/path"
|
369
|
+
Dropbox.should_receive(:check_path).once.with(path).and_return(path)
|
370
|
+
@token_mock.stub!(:get).and_return(@response)
|
371
|
+
|
372
|
+
@session.link(path)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
describe "#metadata" do
|
377
|
+
before :each do
|
378
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
379
|
+
end
|
380
|
+
|
381
|
+
it "should call the API method metadata" do
|
382
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'metadata', { :list => 'true' }, @response, 'some/file', 'sandbox'
|
383
|
+
@session.metadata 'some/file'
|
384
|
+
end
|
385
|
+
|
386
|
+
it "should strip a leading slash" do
|
387
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'metadata', { :list => 'true' }, @response, 'some/file', 'sandbox'
|
388
|
+
@session.metadata '/some/file'
|
389
|
+
end
|
390
|
+
|
391
|
+
it "should set file_limit if :limit is set" do
|
392
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'metadata', { :list => 'true', :file_limit => '123' }, @response, 'some/file', 'sandbox'
|
393
|
+
@session.metadata 'some/file', :limit => 123
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should set list=false if :suppress_list is set" do
|
397
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'metadata', { :list => 'false' }, @response, 'some/file', 'sandbox'
|
398
|
+
@session.metadata 'some/file', :suppress_list => true
|
399
|
+
end
|
400
|
+
|
401
|
+
it "should rescue 406's and re-raise them as TooManyEntriesErrors" do
|
402
|
+
response_acts_as Net::HTTPNotAcceptable
|
403
|
+
@token_mock.stub!(:get).and_return(@response)
|
404
|
+
|
405
|
+
lambda { @session.metadata('a') }.should raise_error(Dropbox::TooManyEntriesError)
|
406
|
+
end
|
407
|
+
|
408
|
+
it "should rescue 404's and re-raise them as FileNotFoundErrors" do
|
409
|
+
response_acts_as Net::HTTPNotFound
|
410
|
+
@token_mock.stub!(:get).and_return(@response)
|
411
|
+
|
412
|
+
lambda { @session.metadata('a') }.should raise_error(Dropbox::FileNotFoundError)
|
413
|
+
end
|
414
|
+
|
415
|
+
it "should re-raise other errors unmodified" do
|
416
|
+
response_acts_as nil
|
417
|
+
@token_mock.stub!(:get).and_return(@response)
|
418
|
+
|
419
|
+
lambda { @session.metadata('a') }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
420
|
+
end
|
421
|
+
|
422
|
+
it "should check the path" do
|
423
|
+
path = "source/path"
|
424
|
+
Dropbox.should_receive(:check_path).once.with(path).and_return(path)
|
425
|
+
@token_mock.stub!(:get).and_return(@response)
|
426
|
+
|
427
|
+
@session.metadata(path)
|
428
|
+
end
|
429
|
+
|
430
|
+
it "should recursively convert the modification date into a Time" do
|
431
|
+
time = Time.now
|
432
|
+
@response.stub!(:body).and_return({ :modified => time.to_s, :hsh => { :modified => time.to_s } }.to_json)
|
433
|
+
@token_mock.stub!(:get).and_return(@response)
|
434
|
+
|
435
|
+
response = @session.metadata('path')
|
436
|
+
|
437
|
+
response.modified.should be_kind_of(Time)
|
438
|
+
response.modified.to_i.should == time.to_i
|
439
|
+
response.hsh.modified.should be_kind_of(Time)
|
440
|
+
response.hsh.modified.to_i.should == time.to_i
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should add a directory? item recursively" do
|
444
|
+
@response.stub!(:body).and_return({ :is_dir => true, :hsh => { :is_dir => false } }.to_json)
|
445
|
+
@token_mock.stub!(:get).and_return(@response)
|
446
|
+
|
447
|
+
response = @session.metadata('path')
|
448
|
+
|
449
|
+
response.directory?.should be_true
|
450
|
+
response.hsh.directory?.should be_false
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
describe "#list" do
|
455
|
+
before :each do
|
456
|
+
@response = mock('metadata')
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should call the metadata method and return the contents attribute" do
|
460
|
+
@response.should_receive(:contents).once.and_return([ 'contents' ])
|
461
|
+
@session.should_receive(:metadata).once.with('my/file', an_instance_of(Hash)).and_return(@response)
|
462
|
+
|
463
|
+
@session.list('my/file').should == [ 'contents' ]
|
464
|
+
end
|
465
|
+
|
466
|
+
it "should not allow suppress_list to be set to true" do
|
467
|
+
@response.stub!(:contents)
|
468
|
+
@session.should_receive(:metadata).once.with('my/file', hash_including(:hash => true, :suppress_list => false)).and_return(@response)
|
469
|
+
|
470
|
+
@session.list('my/file', :suppress_list => true, :hash => true)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
describe "#upload" do
|
475
|
+
before :each do
|
476
|
+
stub_for_upload_testing
|
477
|
+
end
|
478
|
+
|
479
|
+
it "should check the path" do
|
480
|
+
path = "dest/path"
|
481
|
+
Dropbox.should_receive(:check_path).once.with(path).and_return(path)
|
482
|
+
@session.upload(__FILE__, path)
|
483
|
+
end
|
484
|
+
|
485
|
+
describe "parameters" do
|
486
|
+
describe "given a File object" do
|
487
|
+
before :each do
|
488
|
+
@file = File.open(__FILE__)
|
489
|
+
end
|
490
|
+
|
491
|
+
after :each do
|
492
|
+
@file.close
|
493
|
+
end
|
494
|
+
|
495
|
+
it "should use the File object as the stream" do
|
496
|
+
UploadIO.should_receive(:convert!).once.with(@file, anything, File.basename(__FILE__), __FILE__)
|
497
|
+
@session.upload @file, 'remote/'
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
describe "given a String object" do
|
502
|
+
before :each do
|
503
|
+
@string = __FILE__
|
504
|
+
@file = File.new(__FILE__)
|
505
|
+
File.should_receive(:new).once.with(@string).and_return(@file)
|
506
|
+
end
|
507
|
+
|
508
|
+
it "should use the file at that path as the stream" do
|
509
|
+
UploadIO.should_receive(:convert!).once.with(@file, anything, File.basename(__FILE__), __FILE__)
|
510
|
+
@session.upload @string, 'remote/'
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
it "should raise an error if given an unknown argument type" do
|
515
|
+
lambda { @session.upload 123, 'path' }.should raise_error(ArgumentError)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
describe "request" do
|
520
|
+
before :each do
|
521
|
+
@request = mock('Net::HTTPRequest')
|
522
|
+
@request.stub!(:[]=)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "should strip a leading slash from the remote path" do
|
526
|
+
Net::HTTP::Post::Multipart.should_receive(:new).once do |*args|
|
527
|
+
args.first.should eql("/#{Dropbox::VERSION}/files/sandbox/path")
|
528
|
+
@request
|
529
|
+
end
|
530
|
+
|
531
|
+
@session.upload __FILE__, '/path'
|
532
|
+
end
|
533
|
+
|
534
|
+
it "should call the files API method" do
|
535
|
+
Net::HTTP::Post::Multipart.should_receive(:new).once do |*args|
|
536
|
+
args.first.should eql("/#{Dropbox::VERSION}/files/sandbox/path/to/file")
|
537
|
+
@request
|
538
|
+
end
|
539
|
+
|
540
|
+
@session.upload __FILE__, 'path/to/file'
|
541
|
+
end
|
542
|
+
|
543
|
+
it "should use the sandbox root if specified" do
|
544
|
+
Net::HTTP::Post::Multipart.should_receive(:new).once do |*args|
|
545
|
+
args.first.should eql("/#{Dropbox::VERSION}/files/sandbox/path/to/file")
|
546
|
+
@request
|
547
|
+
end
|
548
|
+
|
549
|
+
@session.upload __FILE__, 'path/to/file', :mode => :sandbox
|
550
|
+
end
|
551
|
+
|
552
|
+
it "should set the authorization content header to the signed OAuth request" do
|
553
|
+
Net::HTTP::Post::Multipart.stub!(:new).and_return(@request)
|
554
|
+
@request.should_receive(:[]=).once.with('authorization', 'Oauth, test')
|
555
|
+
|
556
|
+
@session.upload __FILE__, 'blah'
|
557
|
+
end
|
558
|
+
|
559
|
+
it "should create a multipart POST request with the 'file' parameter set to the file of type application/octet-stream" do
|
560
|
+
Net::HTTP::Post::Multipart.should_receive(:new).once.with("/#{Dropbox::VERSION}/files/sandbox/hello", hash_including('file' => an_instance_of(File))).and_return(@request)
|
561
|
+
|
562
|
+
@session.upload __FILE__, 'hello'
|
563
|
+
end
|
564
|
+
|
565
|
+
it "should send the request" do
|
566
|
+
uri = URI.parse(Dropbox::ALTERNATE_HOSTS['files'])
|
567
|
+
Net::HTTP.should_receive(:start).once.with(uri.host, uri.port).and_return(@response)
|
568
|
+
|
569
|
+
@session.upload __FILE__, 'test'
|
570
|
+
end
|
571
|
+
|
572
|
+
it "should send an SSL request" do
|
573
|
+
@session = Dropbox::Session.new('foo', 'bar', :ssl => true)
|
574
|
+
@session.authorize
|
575
|
+
|
576
|
+
uri = URI.parse(Dropbox::ALTERNATE_SSL_HOSTS['files'])
|
577
|
+
Net::HTTP.should_receive(:start).once.with(uri.host, uri.port).and_return(@response)
|
578
|
+
|
579
|
+
@session.upload __FILE__, 'test'
|
580
|
+
end
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
describe "#event_metadata" do
|
585
|
+
it "should call the API method event_metadata" do
|
586
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
587
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'event_metadata', { :root => 'sandbox', :target_events => 'event_json' }, @response
|
588
|
+
@session.event_metadata 'event_json'
|
589
|
+
end
|
590
|
+
|
591
|
+
it "should return the JSON-parsed response" do
|
592
|
+
resp = { :some => { :json => 123 } }
|
593
|
+
@response.stub!(:body).and_return(resp.to_json)
|
594
|
+
@token_mock.stub!(:get).and_return(@response)
|
595
|
+
@session.event_metadata('event_json').should == resp
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
describe "#event_content" do
|
600
|
+
it "should call the API method event_content" do
|
601
|
+
@response.stub!(:body).and_return('content')
|
602
|
+
@response.stub!(:header).and_return('X-Dropbox-Metadata' => '{"a":"b"}')
|
603
|
+
should_receive_api_method_with_arguments @token_mock, :get, 'event_content', { :root => 'sandbox', :target_event => '1%3A2%3A3' }, @response
|
604
|
+
@session.event_content '1:2:3'
|
605
|
+
end
|
606
|
+
|
607
|
+
it "should return the content body and the X-Dropbox-Metadata header JSON" do
|
608
|
+
resp = { 'some' => { 'json' => 123 } }
|
609
|
+
body = "Content here"
|
610
|
+
@response.stub!(:body).and_return(body)
|
611
|
+
@response.should_receive(:header).once.and_return('X-Dropbox-Metadata' => resp.to_json)
|
612
|
+
@token_mock.stub!(:get).and_return(@response)
|
613
|
+
|
614
|
+
@session.event_content('1:2:3').should == [ body, resp ]
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
{
|
619
|
+
:account => [ :get ],
|
620
|
+
:upload => [ :post, __FILE__, 'path/here' ],
|
621
|
+
:copy => [ :post, 'source/file', 'dest/file' ],
|
622
|
+
:move => [ :post, 'source/file', 'dest/file' ],
|
623
|
+
:create_folder => [ :post, 'new/folder' ],
|
624
|
+
:metadata => [ :get, 'some/file' ],
|
625
|
+
:event_metadata => [ :get, 'some_json' ]
|
626
|
+
}.each do |meth, args|
|
627
|
+
describe meth do
|
628
|
+
before :each do
|
629
|
+
stub_for_upload_testing
|
630
|
+
@token_mock.stub!(args.first).and_return(@response)
|
631
|
+
end
|
632
|
+
|
633
|
+
it "should parse the JSON response if successful" do
|
634
|
+
@response.stub!(:body).and_return('{"test":"json"}')
|
635
|
+
@session.send(meth, *(args[1..-1]))
|
636
|
+
end
|
637
|
+
|
638
|
+
it "should raise a ParseError if the JSON is invalid" do
|
639
|
+
@response.stub!(:body).and_return('sdgsdg')
|
640
|
+
lambda { @session.send(meth, *(args[1..-1])) }.should raise_error(Dropbox::ParseError)
|
641
|
+
end
|
642
|
+
|
643
|
+
it "should raise UnsuccessfulResponseError if unsuccessful" do
|
644
|
+
@response.stub!(:kind_of?).and_return(false)
|
645
|
+
lambda { @session.send(meth, *(args[1..-1])) }.should raise_error(Dropbox::UnsuccessfulResponseError)
|
646
|
+
end
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
describe "#mode" do
|
651
|
+
it "should return the correct mode" do
|
652
|
+
@session.mode = :dropbox
|
653
|
+
@session.mode.should eql(:dropbox)
|
654
|
+
|
655
|
+
@session.mode = :sandbox
|
656
|
+
@session.mode.should eql(:sandbox)
|
657
|
+
|
658
|
+
@session.mode = :metadata_only
|
659
|
+
@session.mode.should eql(:metadata_only)
|
660
|
+
end
|
661
|
+
|
662
|
+
it "should be :sandbox by default" do
|
663
|
+
@session.mode.should eql(:sandbox)
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
describe "#mode=" do
|
668
|
+
it "set the API root" do
|
669
|
+
@session.mode = :dropbox
|
670
|
+
@token_mock.should_receive(:get).once do |url, *rest|
|
671
|
+
url.should include('/dropbox')
|
672
|
+
url.should_not include('/sandbox')
|
673
|
+
@response
|
674
|
+
end
|
675
|
+
@session.download 'file'
|
676
|
+
|
677
|
+
@session.mode = :sandbox
|
678
|
+
@token_mock.should_receive(:get).once do |url, *rest|
|
679
|
+
url.should include('/sandbox')
|
680
|
+
url.should_not include('/dropbox')
|
681
|
+
@response
|
682
|
+
end
|
683
|
+
@session.download 'file'
|
684
|
+
|
685
|
+
@session.mode = :metadata_only
|
686
|
+
@token_mock.should_receive(:get).once do |url, *rest|
|
687
|
+
url.should include('/dropbox')
|
688
|
+
url.should_not include('/sandbox')
|
689
|
+
@response
|
690
|
+
end
|
691
|
+
@session.download 'file'
|
692
|
+
end
|
693
|
+
|
694
|
+
it "should raise for invalid modes" do
|
695
|
+
lambda { @session.mode = :foo }.should raise_error(ArgumentError)
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
{
|
700
|
+
:account => [],
|
701
|
+
:copy => [ 'foo', 'bar' ],
|
702
|
+
:create_folder => [ 'foo' ],
|
703
|
+
:delete => [ 'foo' ],
|
704
|
+
:move => [ 'foo', 'bar' ],
|
705
|
+
:link => [ 'foo' ],
|
706
|
+
:metadata => [ 'foo'],
|
707
|
+
:download => [ 'foo' ],
|
708
|
+
:event_metadata => [ 'foo' ],
|
709
|
+
:event_content => [ 'foo' ]
|
710
|
+
}.each do |root_method, args|
|
711
|
+
describe ".#{root_method}" do
|
712
|
+
before :each do
|
713
|
+
@session = Dropbox::Session.new('foo', 'bar', :ssl => true)
|
714
|
+
@session.authorize
|
715
|
+
|
716
|
+
@token_mock.stub!(:get).and_return(@response)
|
717
|
+
@token_mock.stub!(:post).and_return(@response)
|
718
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
719
|
+
@response.stub!(:header).and_return('X-Dropbox-Metadata' => '{"a":"b"}')
|
720
|
+
end
|
721
|
+
|
722
|
+
it "should use the SSL host if :ssl => true is given to the constructor" do
|
723
|
+
Dropbox.should_receive(:api_url).once do |*args|
|
724
|
+
args.last[:ssl].should be_true
|
725
|
+
"http://www.example.com/test"
|
726
|
+
end
|
727
|
+
|
728
|
+
@session.send(root_method, *args)
|
729
|
+
end
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
{
|
734
|
+
:download => [ :get, 'path/to/file' ],
|
735
|
+
:copy => [ :post, 'source/file', 'dest/file' ],
|
736
|
+
:move => [ :post, 'source/file', 'dest/file' ],
|
737
|
+
:create_folder => [ :post, 'new/folder' ],
|
738
|
+
:delete => [ :post, 'some/file' ],
|
739
|
+
:link => [ :get, 'some/file' ],
|
740
|
+
:metadata => [ :get, 'some/file' ],
|
741
|
+
:event_metadata => [ :get, 'some_json' ],
|
742
|
+
:event_content => [ :get, '1:2:3' ]
|
743
|
+
}.each do |root_method, args|
|
744
|
+
describe ".#{root_method}" do
|
745
|
+
before :each do
|
746
|
+
@response.stub!(:body).and_return('{"a":"b"}')
|
747
|
+
@response.stub!(:header).and_return('X-Dropbox-Metadata' => '{"a":"b"}')
|
748
|
+
end
|
749
|
+
|
750
|
+
it "should use the dropbox root if in dropbox mode" do
|
751
|
+
@token_mock.should_receive(args.first).once do |url, *rest|
|
752
|
+
url.should_not include('sandbox')
|
753
|
+
@response
|
754
|
+
end
|
755
|
+
@session.mode = :dropbox
|
756
|
+
@session.send(root_method, *(args[1..-1]))
|
757
|
+
end
|
758
|
+
|
759
|
+
it "should use the sandbox root if in sandbox mode" do
|
760
|
+
@token_mock.should_receive(args.first).once do |url, *rest|
|
761
|
+
url.should include('sandbox')
|
762
|
+
@response
|
763
|
+
end
|
764
|
+
@session.mode = :sandbox
|
765
|
+
@session.send(root_method, *(args[1..-1]))
|
766
|
+
end
|
767
|
+
|
768
|
+
it "should use the dropbox root if in metadata mode" do
|
769
|
+
@token_mock.should_receive(args.first).once do |url, *rest|
|
770
|
+
url.should_not include('sandbox')
|
771
|
+
@response
|
772
|
+
end
|
773
|
+
@session.mode = :metadata_only
|
774
|
+
@session.send(root_method, *(args[1..-1]))
|
775
|
+
end
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|