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.
@@ -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