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