Remove embedded version #s, use Gemfile
[arvados.git] / spec / google / api_client / discovery_spec.rb
1 # encoding:utf-8
2
3 # Copyright 2010 Google Inc.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17
18 require 'spec_helper'
19
20 require 'faraday'
21 require 'faraday/utils'
22 require 'multi_json'
23 require 'compat/multi_json'
24 require 'signet/oauth_1/client'
25 require 'google/api_client'
26 require 'google/api_client/version'
27
28 describe Google::APIClient do
29   CLIENT ||= Google::APIClient.new
30
31   after do
32     # Reset client to not-quite-pristine state
33     CLIENT.key = nil
34     CLIENT.user_ip = nil
35   end
36
37   it 'should raise a type error for bogus authorization' do
38     (lambda do
39       Google::APIClient.new(:authorization => 42)
40     end).should raise_error(TypeError)
41   end
42
43   it 'should not be able to retrieve the discovery document for a bogus API' do
44     (lambda do
45       CLIENT.discovery_document('bogus')
46     end).should raise_error(Google::APIClient::TransmissionError)
47     (lambda do
48       CLIENT.discovered_api('bogus')
49     end).should raise_error(Google::APIClient::TransmissionError)
50   end
51
52   it 'should raise an error for bogus services' do
53     (lambda do
54       CLIENT.discovered_api(42)
55     end).should raise_error(TypeError)
56   end
57
58   it 'should raise an error for bogus services' do
59     (lambda do
60       CLIENT.preferred_version(42)
61     end).should raise_error(TypeError)
62   end
63
64   it 'should raise an error for bogus methods' do
65     (lambda do
66       CLIENT.generate_request(42)
67     end).should raise_error(TypeError)
68   end
69
70   it 'should not return a preferred version for bogus service names' do
71     CLIENT.preferred_version('bogus').should == nil
72   end
73
74   describe 'with the prediction API' do
75     before do
76       CLIENT.authorization = nil
77       # The prediction API no longer exposes a v1, so we have to be
78       # careful about looking up the wrong API version.
79       @prediction = CLIENT.discovered_api('prediction', 'v1.2')
80     end
81
82     it 'should correctly determine the discovery URI' do
83       CLIENT.discovery_uri('prediction').should ===
84         'https://www.googleapis.com/discovery/v1/apis/prediction/v1/rest'
85     end
86
87     it 'should correctly determine the discovery URI if :user_ip is set' do
88       CLIENT.user_ip = '127.0.0.1'
89       request = CLIENT.generate_request(
90         :http_method => 'GET',
91         :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
92         :authenticated => false
93       )
94       request.to_env(Faraday.default_connection)[:url].to_s.should === (
95         'https://www.googleapis.com/discovery/v1/apis/prediction/v1.2/rest' +
96         '?userIp=127.0.0.1'
97       )
98     end
99
100     it 'should correctly determine the discovery URI if :key is set' do
101       CLIENT.key = 'qwerty'
102       request = CLIENT.generate_request(
103         :http_method => 'GET',
104         :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
105         :authenticated => false
106       )
107       request.to_env(Faraday.default_connection)[:url].to_s.should === (
108         'https://www.googleapis.com/discovery/v1/apis/prediction/v1.2/rest' +
109         '?key=qwerty'
110       )
111     end
112
113     it 'should correctly determine the discovery URI if both are set' do
114       CLIENT.key = 'qwerty'
115       CLIENT.user_ip = '127.0.0.1'
116       request = CLIENT.generate_request(
117         :http_method => 'GET',
118         :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
119         :authenticated => false
120       )
121       Addressable::URI.parse(
122         request.to_env(Faraday.default_connection)[:url]
123       ).query_values.should == {
124         'key' => 'qwerty',
125         'userIp' => '127.0.0.1'
126       }
127     end
128
129     it 'should correctly generate API objects' do
130       CLIENT.discovered_api('prediction', 'v1.2').name.should == 'prediction'
131       CLIENT.discovered_api('prediction', 'v1.2').version.should == 'v1.2'
132       CLIENT.discovered_api(:prediction, 'v1.2').name.should == 'prediction'
133       CLIENT.discovered_api(:prediction, 'v1.2').version.should == 'v1.2'
134     end
135
136     it 'should discover methods' do
137       CLIENT.discovered_method(
138         'prediction.training.insert', 'prediction', 'v1.2'
139       ).name.should == 'insert'
140       CLIENT.discovered_method(
141         :'prediction.training.insert', :prediction, 'v1.2'
142       ).name.should == 'insert'
143       CLIENT.discovered_method(
144         'prediction.training.delete', 'prediction', 'v1.2'
145       ).name.should == 'delete'
146     end
147
148     it 'should define the origin API in discovered methods' do
149       CLIENT.discovered_method(
150         'prediction.training.insert', 'prediction', 'v1.2'
151       ).api.name.should == 'prediction'
152     end
153
154     it 'should not find methods that are not in the discovery document' do
155       CLIENT.discovered_method(
156         'prediction.bogus', 'prediction', 'v1.2'
157       ).should == nil
158     end
159
160     it 'should raise an error for bogus methods' do
161       (lambda do
162         CLIENT.discovered_method(42, 'prediction', 'v1.2')
163       end).should raise_error(TypeError)
164     end
165
166     it 'should raise an error for bogus methods' do
167       (lambda do
168         CLIENT.generate_request(CLIENT.discovered_api('prediction', 'v1.2'))
169       end).should raise_error(TypeError)
170     end
171
172     it 'should correctly determine the preferred version' do
173       CLIENT.preferred_version('prediction').version.should_not == 'v1'
174       CLIENT.preferred_version(:prediction).version.should_not == 'v1'
175     end
176
177     it 'should return a batch path' do
178       CLIENT.discovered_api('prediction', 'v1.2').batch_path.should_not be_nil
179     end
180
181     it 'should generate valid requests' do
182       request = CLIENT.generate_request(
183         :api_method => @prediction.training.insert,
184         :parameters => {'data' => '12345'}
185       )
186       request.method.should == :post
187       request.to_env(Faraday.default_connection)[:url].to_s.should ===
188         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
189       request.headers.should be_empty
190       request.body.should == ''
191     end
192
193     it 'should generate valid requests when repeated parameters are passed' do
194       request = CLIENT.generate_request(
195         :api_method => @prediction.training.insert,
196         :parameters => [['data', '1'], ['data','2']]
197       )
198       request.method.should == :post
199       request.to_env(Faraday.default_connection)[:url].to_s.should ===
200         'https://www.googleapis.com/prediction/v1.2/training?data=1&data=2'
201     end
202
203     it 'should generate requests against the correct URIs' do
204       request = CLIENT.generate_request(
205         :api_method => @prediction.training.insert,
206         :parameters => {'data' => '12345'}
207       )
208       request.to_env(Faraday.default_connection)[:url].to_s.should ===
209         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
210     end
211
212     it 'should generate requests against the correct URIs' do
213       request = CLIENT.generate_request(
214         :api_method => @prediction.training.insert,
215         :parameters => {'data' => '12345'}
216       )
217       request.to_env(Faraday.default_connection)[:url].to_s.should ===
218         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
219     end
220
221     it 'should allow modification to the base URIs for testing purposes' do
222       # Using a new client instance here to avoid caching rebased discovery doc
223       prediction_rebase =
224         Google::APIClient.new.discovered_api('prediction', 'v1.2')
225       prediction_rebase.method_base =
226         'https://testing-domain.example.com/prediction/v1.2/'
227       request = CLIENT.generate_request(
228         :api_method => prediction_rebase.training.insert,
229         :parameters => {'data' => '123'}
230       )
231       request.to_env(Faraday.default_connection)[:url].to_s.should === (
232         'https://testing-domain.example.com/' +
233         'prediction/v1.2/training?data=123'
234       )
235     end
236
237     it 'should generate OAuth 1 requests' do
238       CLIENT.authorization = :oauth_1
239       CLIENT.authorization.token_credential_key = '12345'
240       CLIENT.authorization.token_credential_secret = '12345'
241       request = CLIENT.generate_request(
242         :api_method => @prediction.training.insert,
243         :parameters => {'data' => '12345'}
244       )
245       request.headers.should have_key('Authorization')
246       request.headers['Authorization'].should =~ /^OAuth/
247     end
248
249     it 'should generate OAuth 2 requests' do
250       CLIENT.authorization = :oauth_2
251       CLIENT.authorization.access_token = '12345'
252       request = CLIENT.generate_request(
253         :api_method => @prediction.training.insert,
254         :parameters => {'data' => '12345'}
255       )
256       request.headers.should have_key('Authorization')
257       request.headers['Authorization'].should =~ /^Bearer/
258     end
259
260     it 'should not be able to execute improperly authorized requests' do
261       CLIENT.authorization = :oauth_1
262       CLIENT.authorization.token_credential_key = '12345'
263       CLIENT.authorization.token_credential_secret = '12345'
264       result = CLIENT.execute(
265         @prediction.training.insert,
266         {'data' => '12345'}
267       )
268       result.response.status.should == 401
269     end
270
271     it 'should not be able to execute improperly authorized requests' do
272       CLIENT.authorization = :oauth_2
273       CLIENT.authorization.access_token = '12345'
274       result = CLIENT.execute(
275         @prediction.training.insert,
276         {'data' => '12345'}
277       )
278       result.response.status.should == 401
279     end
280
281     it 'should not be able to execute improperly authorized requests' do
282       (lambda do
283         CLIENT.authorization = :oauth_1
284         CLIENT.authorization.token_credential_key = '12345'
285         CLIENT.authorization.token_credential_secret = '12345'
286         result = CLIENT.execute!(
287           @prediction.training.insert,
288           {'data' => '12345'}
289         )
290       end).should raise_error(Google::APIClient::ClientError)
291     end
292
293     it 'should not be able to execute improperly authorized requests' do
294       (lambda do
295         CLIENT.authorization = :oauth_2
296         CLIENT.authorization.access_token = '12345'
297         result = CLIENT.execute!(
298           @prediction.training.insert,
299           {'data' => '12345'}
300         )
301       end).should raise_error(Google::APIClient::ClientError)
302     end
303
304     it 'should correctly handle unnamed parameters' do
305       CLIENT.authorization = :oauth_2
306       CLIENT.authorization.access_token = '12345'
307       result = CLIENT.execute(
308         @prediction.training.insert,
309         {},
310         MultiJson.dump({"id" => "bucket/object"}),
311         {'Content-Type' => 'application/json'}
312       )
313       result.request.headers['Content-Type'].should == 'application/json'
314     end
315   end
316
317   describe 'with the plus API' do
318     before do
319       CLIENT.authorization = nil
320       @plus = CLIENT.discovered_api('plus')
321     end
322
323     it 'should correctly determine the discovery URI' do
324       CLIENT.discovery_uri('plus').should ===
325         'https://www.googleapis.com/discovery/v1/apis/plus/v1/rest'
326     end
327
328     it 'should find APIs that are in the discovery document' do
329       CLIENT.discovered_api('plus').name.should == 'plus'
330       CLIENT.discovered_api('plus').version.should == 'v1'
331       CLIENT.discovered_api(:plus).name.should == 'plus'
332       CLIENT.discovered_api(:plus).version.should == 'v1'
333     end
334
335     it 'should find methods that are in the discovery document' do
336       # TODO(bobaman) Fix this when the RPC names are correct
337       CLIENT.discovered_method(
338         'plus.activities.list', 'plus'
339       ).name.should == 'list'
340     end
341
342     it 'should define the origin API in discovered methods' do
343       CLIENT.discovered_method(
344         'plus.activities.list', 'plus'
345       ).api.name.should == 'plus'
346     end
347
348     it 'should not find methods that are not in the discovery document' do
349       CLIENT.discovered_method('plus.bogus', 'plus').should == nil
350     end
351
352     it 'should generate requests against the correct URIs' do
353       request = CLIENT.generate_request(
354         :api_method => @plus.activities.list,
355         :parameters => {
356           'userId' => '107807692475771887386', 'collection' => 'public'
357         },
358         :authenticated => false
359       )
360       request.to_env(Faraday.default_connection)[:url].to_s.should === (
361         'https://www.googleapis.com/plus/v1/' +
362         'people/107807692475771887386/activities/public'
363       )
364     end
365
366     it 'should correctly validate parameters' do
367       (lambda do
368         CLIENT.generate_request(
369           :api_method => @plus.activities.list,
370           :parameters => {'alt' => 'json'},
371           :authenticated => false
372         )
373       end).should raise_error(ArgumentError)
374     end
375
376     it 'should correctly validate parameters' do
377       (lambda do
378         CLIENT.generate_request(
379           :api_method => @plus.activities.list,
380           :parameters => {
381             'userId' => '107807692475771887386', 'collection' => 'bogus'
382           },
383           :authenticated => false
384         )
385       end).should raise_error(ArgumentError)
386     end
387   end
388   
389 =begin
390   describe 'with the latitude API' do
391     before do
392       CLIENT.authorization = nil
393       @latitude = CLIENT.discovered_api('latitude')
394     end
395
396     it 'should correctly determine the discovery URI' do
397       CLIENT.discovery_uri('latitude').should ===
398         'https://www.googleapis.com/discovery/v1/apis/latitude/v1/rest'
399     end
400
401     it 'should find APIs that are in the discovery document' do
402       CLIENT.discovered_api('latitude').name.should == 'latitude'
403       CLIENT.discovered_api('latitude').version.should == 'v1'
404     end
405
406     it 'should return a batch path' do
407       CLIENT.discovered_api('latitude').batch_path.should_not be_nil
408     end
409
410     it 'should find methods that are in the discovery document' do
411       CLIENT.discovered_method(
412         'latitude.currentLocation.get', 'latitude'
413       ).name.should == 'get'
414     end
415
416     it 'should define the origin API in discovered methods' do
417       CLIENT.discovered_method(
418         'latitude.currentLocation.get', 'latitude'
419       ).api.name.should == 'latitude'
420     end
421
422     it 'should not find methods that are not in the discovery document' do
423       CLIENT.discovered_method('latitude.bogus', 'latitude').should == nil
424     end
425
426     it 'should generate requests against the correct URIs' do
427       request = CLIENT.generate_request(
428         :api_method => 'latitude.currentLocation.get',
429         :authenticated => false
430       )
431       request.to_env(Faraday.default_connection)[:url].to_s.should ===
432         'https://www.googleapis.com/latitude/v1/currentLocation'
433     end
434
435     it 'should generate requests against the correct URIs' do
436       request = CLIENT.generate_request(
437         :api_method => @latitude.current_location.get,
438         :authenticated => false
439       )
440       request.to_env(Faraday.default_connection)[:url].to_s.should ===
441         'https://www.googleapis.com/latitude/v1/currentLocation'
442     end
443
444     it 'should not be able to execute requests without authorization' do
445       result = CLIENT.execute(
446         :api_method => 'latitude.currentLocation.get',
447         :authenticated => false
448       )
449       result.response.status.should == 401
450     end
451   end
452 =end
453
454   describe 'with the moderator API' do
455     before do
456       CLIENT.authorization = nil
457       @moderator = CLIENT.discovered_api('moderator')
458     end
459
460     it 'should correctly determine the discovery URI' do
461       CLIENT.discovery_uri('moderator').should ===
462         'https://www.googleapis.com/discovery/v1/apis/moderator/v1/rest'
463     end
464
465     it 'should find APIs that are in the discovery document' do
466       CLIENT.discovered_api('moderator').name.should == 'moderator'
467       CLIENT.discovered_api('moderator').version.should == 'v1'
468     end
469
470     it 'should find methods that are in the discovery document' do
471       CLIENT.discovered_method(
472         'moderator.profiles.get', 'moderator'
473       ).name.should == 'get'
474     end
475
476     it 'should define the origin API in discovered methods' do
477       CLIENT.discovered_method(
478         'moderator.profiles.get', 'moderator'
479       ).api.name.should == 'moderator'
480     end
481
482     it 'should not find methods that are not in the discovery document' do
483       CLIENT.discovered_method('moderator.bogus', 'moderator').should == nil
484     end
485
486     it 'should return a batch path' do
487       CLIENT.discovered_api('moderator').batch_path.should_not be_nil
488     end
489
490     it 'should generate requests against the correct URIs' do
491       request = CLIENT.generate_request(
492         :api_method => 'moderator.profiles.get',
493         :authenticated => false
494       )
495       request.to_env(Faraday.default_connection)[:url].to_s.should ===
496         'https://www.googleapis.com/moderator/v1/profiles/@me'
497     end
498
499     it 'should generate requests against the correct URIs' do
500       request = CLIENT.generate_request(
501         :api_method => @moderator.profiles.get,
502         :authenticated => false
503       )
504       request.to_env(Faraday.default_connection)[:url].to_s.should ===
505         'https://www.googleapis.com/moderator/v1/profiles/@me'
506     end
507
508     it 'should not be able to execute requests without authorization' do
509       result = CLIENT.execute(
510         'moderator.profiles.get',
511         {},
512         '',
513         [],
514         {:authenticated => false}
515       )
516       result.response.status.should == 401
517     end
518   end
519
520   describe 'with the adsense API' do
521     before do
522       CLIENT.authorization = nil
523       @adsense = CLIENT.discovered_api('adsense', 'v1')
524     end
525
526     it 'should correctly determine the discovery URI' do
527       CLIENT.discovery_uri('adsense').should ===
528         'https://www.googleapis.com/discovery/v1/apis/adsense/v1/rest'
529     end
530
531     it 'should find APIs that are in the discovery document' do
532       CLIENT.discovered_api('adsense').name.should == 'adsense'
533       CLIENT.discovered_api('adsense').version.should == 'v1'
534     end
535
536     it 'should return a batch path' do
537       CLIENT.discovered_api('adsense').batch_path.should_not be_nil
538     end
539
540     it 'should find methods that are in the discovery document' do
541       CLIENT.discovered_method(
542         'adsense.reports.generate', 'adsense'
543       ).name.should == 'generate'
544     end
545
546     it 'should not find methods that are not in the discovery document' do
547       CLIENT.discovered_method('adsense.bogus', 'adsense').should == nil
548     end
549
550     it 'should generate requests against the correct URIs' do
551       request = CLIENT.generate_request(
552         :api_method => 'adsense.adclients.list',
553         :authenticated => false
554       )
555       request.to_env(Faraday.default_connection)[:url].to_s.should ===
556         'https://www.googleapis.com/adsense/v1/adclients'
557     end
558
559     it 'should generate requests against the correct URIs' do
560       request = CLIENT.generate_request(
561         :api_method => @adsense.adclients.list,
562         :authenticated => false
563       )
564       request.to_env(Faraday.default_connection)[:url].to_s.should ===
565         'https://www.googleapis.com/adsense/v1/adclients'
566     end
567
568     it 'should not be able to execute requests without authorization' do
569       result = CLIENT.execute(
570         :api_method => 'adsense.adclients.list',
571         :authenticated => false
572       )
573       result.response.status.should == 401
574     end
575
576     it 'should fail when validating missing required parameters' do
577       (lambda do
578         CLIENT.generate_request(
579           :api_method => @adsense.reports.generate,
580           :authenticated => false
581         )
582       end).should raise_error(ArgumentError)
583     end
584
585     it 'should succeed when validating parameters in a correct call' do
586       (lambda do
587         CLIENT.generate_request(
588           :api_method => @adsense.reports.generate,
589           :parameters => {
590             'startDate' => '2000-01-01',
591             'endDate' => '2010-01-01',
592             'dimension' => 'DATE',
593             'metric' => 'PAGE_VIEWS'
594           },
595           :authenticated => false
596         )
597       end).should_not raise_error
598     end
599
600     it 'should fail when validating parameters with invalid values' do
601       (lambda do
602         CLIENT.generate_request(
603           :api_method => @adsense.reports.generate,
604           :parameters => {
605             'startDate' => '2000-01-01',
606             'endDate' => '2010-01-01',
607             'dimension' => 'BAD_CHARACTERS=-&*(£&',
608             'metric' => 'PAGE_VIEWS'
609           },
610           :authenticated => false
611         )
612       end).should raise_error(ArgumentError)
613     end
614
615     it 'should succeed when validating repeated parameters in a correct call' do
616       (lambda do
617         CLIENT.generate_request(
618           :api_method => @adsense.reports.generate,
619           :parameters => {
620             'startDate' => '2000-01-01',
621             'endDate' => '2010-01-01',
622             'dimension' => ['DATE', 'PRODUCT_CODE'],
623             'metric' => ['PAGE_VIEWS', 'CLICKS']
624           },
625           :authenticated => false
626         )
627       end).should_not raise_error
628     end
629
630     it 'should fail when validating incorrect repeated parameters' do
631       (lambda do
632         CLIENT.generate_request(
633           :api_method => @adsense.reports.generate,
634           :parameters => {
635             'startDate' => '2000-01-01',
636             'endDate' => '2010-01-01',
637             'dimension' => ['DATE', 'BAD_CHARACTERS=-&*(£&'],
638             'metric' => ['PAGE_VIEWS', 'CLICKS']
639           },
640           :authenticated => false
641         )
642       end).should raise_error(ArgumentError)
643     end
644   end
645
646   describe 'with the Drive API' do
647     before do
648       CLIENT.authorization = nil
649       @drive = CLIENT.discovered_api('drive', 'v1')
650     end
651
652     it 'should include media upload info methods' do
653       @drive.files.insert.media_upload.should_not == nil
654     end
655
656     it 'should include accepted media types' do
657       @drive.files.insert.media_upload.accepted_types.should_not be_empty
658     end
659
660     it 'should have an upload path' do
661       @drive.files.insert.media_upload.uri_template.should_not == nil
662     end
663
664     it 'should have a max file size' do
665       @drive.files.insert.media_upload.max_size.should_not == nil
666     end
667   end
668 end