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 unless defined?(CLIENT)
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       pending("This is caused by Faraday's encoding of query parameters.")
195       request = CLIENT.generate_request(
196         :api_method => @prediction.training.insert,
197         :parameters => [['data', '1'], ['data','2']]
198       )
199       request.method.should == :post
200       request.to_env(Faraday.default_connection)[:url].to_s.should ===
201         'https://www.googleapis.com/prediction/v1.2/training?data=1&data=2'
202     end
203
204     it 'should generate requests against the correct URIs' do
205       request = CLIENT.generate_request(
206         :api_method => @prediction.training.insert,
207         :parameters => {'data' => '12345'}
208       )
209       request.to_env(Faraday.default_connection)[:url].to_s.should ===
210         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
211     end
212
213     it 'should generate requests against the correct URIs' do
214       request = CLIENT.generate_request(
215         :api_method => @prediction.training.insert,
216         :parameters => {'data' => '12345'}
217       )
218       request.to_env(Faraday.default_connection)[:url].to_s.should ===
219         'https://www.googleapis.com/prediction/v1.2/training?data=12345'
220     end
221
222     it 'should allow modification to the base URIs for testing purposes' do
223       # Using a new client instance here to avoid caching rebased discovery doc
224       prediction_rebase =
225         Google::APIClient.new.discovered_api('prediction', 'v1.2')
226       prediction_rebase.method_base =
227         'https://testing-domain.example.com/prediction/v1.2/'
228       request = CLIENT.generate_request(
229         :api_method => prediction_rebase.training.insert,
230         :parameters => {'data' => '123'}
231       )
232       request.to_env(Faraday.default_connection)[:url].to_s.should === (
233         'https://testing-domain.example.com/' +
234         'prediction/v1.2/training?data=123'
235       )
236     end
237
238     it 'should generate OAuth 1 requests' do
239       CLIENT.authorization = :oauth_1
240       CLIENT.authorization.token_credential_key = '12345'
241       CLIENT.authorization.token_credential_secret = '12345'
242       request = CLIENT.generate_request(
243         :api_method => @prediction.training.insert,
244         :parameters => {'data' => '12345'}
245       )
246       request.headers.should have_key('Authorization')
247       request.headers['Authorization'].should =~ /^OAuth/
248     end
249
250     it 'should generate OAuth 2 requests' do
251       CLIENT.authorization = :oauth_2
252       CLIENT.authorization.access_token = '12345'
253       request = CLIENT.generate_request(
254         :api_method => @prediction.training.insert,
255         :parameters => {'data' => '12345'}
256       )
257       request.headers.should have_key('Authorization')
258       request.headers['Authorization'].should =~ /^Bearer/
259     end
260
261     it 'should not be able to execute improperly authorized requests' do
262       CLIENT.authorization = :oauth_1
263       CLIENT.authorization.token_credential_key = '12345'
264       CLIENT.authorization.token_credential_secret = '12345'
265       result = CLIENT.execute(
266         @prediction.training.insert,
267         {'data' => '12345'}
268       )
269       result.response.status.should == 401
270     end
271
272     it 'should not be able to execute improperly authorized requests' do
273       CLIENT.authorization = :oauth_2
274       CLIENT.authorization.access_token = '12345'
275       result = CLIENT.execute(
276         @prediction.training.insert,
277         {'data' => '12345'}
278       )
279       result.response.status.should == 401
280     end
281
282     it 'should not be able to execute improperly authorized requests' do
283       (lambda do
284         CLIENT.authorization = :oauth_1
285         CLIENT.authorization.token_credential_key = '12345'
286         CLIENT.authorization.token_credential_secret = '12345'
287         result = CLIENT.execute!(
288           @prediction.training.insert,
289           {'data' => '12345'}
290         )
291       end).should raise_error(Google::APIClient::ClientError)
292     end
293
294     it 'should not be able to execute improperly authorized requests' do
295       (lambda do
296         CLIENT.authorization = :oauth_2
297         CLIENT.authorization.access_token = '12345'
298         result = CLIENT.execute!(
299           @prediction.training.insert,
300           {'data' => '12345'}
301         )
302       end).should raise_error(Google::APIClient::ClientError)
303     end
304
305     it 'should correctly handle unnamed parameters' do
306       CLIENT.authorization = :oauth_2
307       CLIENT.authorization.access_token = '12345'
308       result = CLIENT.execute(
309         @prediction.training.insert,
310         {},
311         MultiJson.dump({"id" => "bucket/object"}),
312         {'Content-Type' => 'application/json'}
313       )
314       result.request.headers['Content-Type'].should == 'application/json'
315     end
316   end
317
318   describe 'with the plus API' do
319     before do
320       CLIENT.authorization = nil
321       @plus = CLIENT.discovered_api('plus')
322     end
323
324     it 'should correctly determine the discovery URI' do
325       CLIENT.discovery_uri('plus').should ===
326         'https://www.googleapis.com/discovery/v1/apis/plus/v1/rest'
327     end
328
329     it 'should find APIs that are in the discovery document' do
330       CLIENT.discovered_api('plus').name.should == 'plus'
331       CLIENT.discovered_api('plus').version.should == 'v1'
332       CLIENT.discovered_api(:plus).name.should == 'plus'
333       CLIENT.discovered_api(:plus).version.should == 'v1'
334     end
335
336     it 'should find methods that are in the discovery document' do
337       # TODO(bobaman) Fix this when the RPC names are correct
338       CLIENT.discovered_method(
339         'plus.activities.list', 'plus'
340       ).name.should == 'list'
341     end
342
343     it 'should define the origin API in discovered methods' do
344       CLIENT.discovered_method(
345         'plus.activities.list', 'plus'
346       ).api.name.should == 'plus'
347     end
348
349     it 'should not find methods that are not in the discovery document' do
350       CLIENT.discovered_method('plus.bogus', 'plus').should == nil
351     end
352
353     it 'should generate requests against the correct URIs' do
354       request = CLIENT.generate_request(
355         :api_method => @plus.activities.list,
356         :parameters => {
357           'userId' => '107807692475771887386', 'collection' => 'public'
358         },
359         :authenticated => false
360       )
361       request.to_env(Faraday.default_connection)[:url].to_s.should === (
362         'https://www.googleapis.com/plus/v1/' +
363         'people/107807692475771887386/activities/public'
364       )
365     end
366
367     it 'should correctly validate parameters' do
368       (lambda do
369         CLIENT.generate_request(
370           :api_method => @plus.activities.list,
371           :parameters => {'alt' => 'json'},
372           :authenticated => false
373         )
374       end).should raise_error(ArgumentError)
375     end
376
377     it 'should correctly validate parameters' do
378       (lambda do
379         CLIENT.generate_request(
380           :api_method => @plus.activities.list,
381           :parameters => {
382             'userId' => '107807692475771887386', 'collection' => 'bogus'
383           },
384           :authenticated => false
385         )
386       end).should raise_error(ArgumentError)
387     end
388   end
389   
390 =begin
391   describe 'with the latitude API' do
392     before do
393       CLIENT.authorization = nil
394       @latitude = CLIENT.discovered_api('latitude')
395     end
396
397     it 'should correctly determine the discovery URI' do
398       CLIENT.discovery_uri('latitude').should ===
399         'https://www.googleapis.com/discovery/v1/apis/latitude/v1/rest'
400     end
401
402     it 'should find APIs that are in the discovery document' do
403       CLIENT.discovered_api('latitude').name.should == 'latitude'
404       CLIENT.discovered_api('latitude').version.should == 'v1'
405     end
406
407     it 'should return a batch path' do
408       CLIENT.discovered_api('latitude').batch_path.should_not be_nil
409     end
410
411     it 'should find methods that are in the discovery document' do
412       CLIENT.discovered_method(
413         'latitude.currentLocation.get', 'latitude'
414       ).name.should == 'get'
415     end
416
417     it 'should define the origin API in discovered methods' do
418       CLIENT.discovered_method(
419         'latitude.currentLocation.get', 'latitude'
420       ).api.name.should == 'latitude'
421     end
422
423     it 'should not find methods that are not in the discovery document' do
424       CLIENT.discovered_method('latitude.bogus', 'latitude').should == nil
425     end
426
427     it 'should generate requests against the correct URIs' do
428       request = CLIENT.generate_request(
429         :api_method => 'latitude.currentLocation.get',
430         :authenticated => false
431       )
432       request.to_env(Faraday.default_connection)[:url].to_s.should ===
433         'https://www.googleapis.com/latitude/v1/currentLocation'
434     end
435
436     it 'should generate requests against the correct URIs' do
437       request = CLIENT.generate_request(
438         :api_method => @latitude.current_location.get,
439         :authenticated => false
440       )
441       request.to_env(Faraday.default_connection)[:url].to_s.should ===
442         'https://www.googleapis.com/latitude/v1/currentLocation'
443     end
444
445     it 'should not be able to execute requests without authorization' do
446       result = CLIENT.execute(
447         :api_method => 'latitude.currentLocation.get',
448         :authenticated => false
449       )
450       result.response.status.should == 401
451     end
452   end
453 =end
454
455   describe 'with the moderator API' do
456     before do
457       CLIENT.authorization = nil
458       @moderator = CLIENT.discovered_api('moderator')
459     end
460
461     it 'should correctly determine the discovery URI' do
462       CLIENT.discovery_uri('moderator').should ===
463         'https://www.googleapis.com/discovery/v1/apis/moderator/v1/rest'
464     end
465
466     it 'should find APIs that are in the discovery document' do
467       CLIENT.discovered_api('moderator').name.should == 'moderator'
468       CLIENT.discovered_api('moderator').version.should == 'v1'
469     end
470
471     it 'should find methods that are in the discovery document' do
472       CLIENT.discovered_method(
473         'moderator.profiles.get', 'moderator'
474       ).name.should == 'get'
475     end
476
477     it 'should define the origin API in discovered methods' do
478       CLIENT.discovered_method(
479         'moderator.profiles.get', 'moderator'
480       ).api.name.should == 'moderator'
481     end
482
483     it 'should not find methods that are not in the discovery document' do
484       CLIENT.discovered_method('moderator.bogus', 'moderator').should == nil
485     end
486
487     it 'should return a batch path' do
488       CLIENT.discovered_api('moderator').batch_path.should_not be_nil
489     end
490
491     it 'should generate requests against the correct URIs' do
492       request = CLIENT.generate_request(
493         :api_method => 'moderator.profiles.get',
494         :authenticated => false
495       )
496       request.to_env(Faraday.default_connection)[:url].to_s.should ===
497         'https://www.googleapis.com/moderator/v1/profiles/@me'
498     end
499
500     it 'should generate requests against the correct URIs' do
501       request = CLIENT.generate_request(
502         :api_method => @moderator.profiles.get,
503         :authenticated => false
504       )
505       request.to_env(Faraday.default_connection)[:url].to_s.should ===
506         'https://www.googleapis.com/moderator/v1/profiles/@me'
507     end
508
509     it 'should not be able to execute requests without authorization' do
510       result = CLIENT.execute(
511         'moderator.profiles.get',
512         {},
513         '',
514         [],
515         {:authenticated => false}
516       )
517       result.response.status.should == 401
518     end
519   end
520
521   describe 'with the adsense API' do
522     before do
523       CLIENT.authorization = nil
524       @adsense = CLIENT.discovered_api('adsense', 'v1')
525     end
526
527     it 'should correctly determine the discovery URI' do
528       CLIENT.discovery_uri('adsense').should ===
529         'https://www.googleapis.com/discovery/v1/apis/adsense/v1/rest'
530     end
531
532     it 'should find APIs that are in the discovery document' do
533       CLIENT.discovered_api('adsense').name.should == 'adsense'
534       CLIENT.discovered_api('adsense').version.should == 'v1'
535     end
536
537     it 'should return a batch path' do
538       CLIENT.discovered_api('adsense').batch_path.should_not be_nil
539     end
540
541     it 'should find methods that are in the discovery document' do
542       CLIENT.discovered_method(
543         'adsense.reports.generate', 'adsense'
544       ).name.should == 'generate'
545     end
546
547     it 'should not find methods that are not in the discovery document' do
548       CLIENT.discovered_method('adsense.bogus', 'adsense').should == nil
549     end
550
551     it 'should generate requests against the correct URIs' do
552       request = CLIENT.generate_request(
553         :api_method => 'adsense.adclients.list',
554         :authenticated => false
555       )
556       request.to_env(Faraday.default_connection)[:url].to_s.should ===
557         'https://www.googleapis.com/adsense/v1/adclients'
558     end
559
560     it 'should generate requests against the correct URIs' do
561       request = CLIENT.generate_request(
562         :api_method => @adsense.adclients.list,
563         :authenticated => false
564       )
565       request.to_env(Faraday.default_connection)[:url].to_s.should ===
566         'https://www.googleapis.com/adsense/v1/adclients'
567     end
568
569     it 'should not be able to execute requests without authorization' do
570       result = CLIENT.execute(
571         :api_method => 'adsense.adclients.list',
572         :authenticated => false
573       )
574       result.response.status.should == 401
575     end
576
577     it 'should fail when validating missing required parameters' do
578       (lambda do
579         CLIENT.generate_request(
580           :api_method => @adsense.reports.generate,
581           :authenticated => false
582         )
583       end).should raise_error(ArgumentError)
584     end
585
586     it 'should succeed when validating parameters in a correct call' do
587       (lambda do
588         CLIENT.generate_request(
589           :api_method => @adsense.reports.generate,
590           :parameters => {
591             'startDate' => '2000-01-01',
592             'endDate' => '2010-01-01',
593             'dimension' => 'DATE',
594             'metric' => 'PAGE_VIEWS'
595           },
596           :authenticated => false
597         )
598       end).should_not raise_error
599     end
600
601     it 'should fail when validating parameters with invalid values' do
602       (lambda do
603         CLIENT.generate_request(
604           :api_method => @adsense.reports.generate,
605           :parameters => {
606             'startDate' => '2000-01-01',
607             'endDate' => '2010-01-01',
608             'dimension' => 'BAD_CHARACTERS=-&*(£&',
609             'metric' => 'PAGE_VIEWS'
610           },
611           :authenticated => false
612         )
613       end).should raise_error(ArgumentError)
614     end
615
616     it 'should succeed when validating repeated parameters in a correct call' do
617       (lambda do
618         CLIENT.generate_request(
619           :api_method => @adsense.reports.generate,
620           :parameters => {
621             'startDate' => '2000-01-01',
622             'endDate' => '2010-01-01',
623             'dimension' => ['DATE', 'PRODUCT_CODE'],
624             'metric' => ['PAGE_VIEWS', 'CLICKS']
625           },
626           :authenticated => false
627         )
628       end).should_not raise_error
629     end
630
631     it 'should fail when validating incorrect repeated parameters' do
632       (lambda do
633         CLIENT.generate_request(
634           :api_method => @adsense.reports.generate,
635           :parameters => {
636             'startDate' => '2000-01-01',
637             'endDate' => '2010-01-01',
638             'dimension' => ['DATE', 'BAD_CHARACTERS=-&*(£&'],
639             'metric' => ['PAGE_VIEWS', 'CLICKS']
640           },
641           :authenticated => false
642         )
643       end).should raise_error(ArgumentError)
644     end
645   end
646
647   describe 'with the Drive API' do
648     before do
649       CLIENT.authorization = nil
650       @drive = CLIENT.discovered_api('drive', 'v1')
651     end
652
653     it 'should include media upload info methods' do
654       @drive.files.insert.media_upload.should_not == nil
655     end
656
657     it 'should include accepted media types' do
658       @drive.files.insert.media_upload.accepted_types.should_not be_empty
659     end
660
661     it 'should have an upload path' do
662       @drive.files.insert.media_upload.uri_template.should_not == nil
663     end
664
665     it 'should have a max file size' do
666       @drive.files.insert.media_upload.max_size.should_not == nil
667     end
668   end
669 end