3 # Copyright 2010 Google Inc.
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
22 require 'compat/multi_json'
23 require 'signet/oauth_1/client'
24 require 'google/api_client'
26 RSpec.describe Google::APIClient do
27 include ConnectionHelpers
28 CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
31 # Reset client to not-quite-pristine state
36 it 'should raise a type error for bogus authorization' do
38 Google::APIClient.new(:application_name => 'API Client Tests', :authorization => 42)
39 end).to raise_error(TypeError)
42 it 'should not be able to retrieve the discovery document for a bogus API' do
44 CLIENT.discovery_document('bogus')
45 end).to raise_error(Google::APIClient::TransmissionError)
47 CLIENT.discovered_api('bogus')
48 end).to raise_error(Google::APIClient::TransmissionError)
51 it 'should raise an error for bogus services' do
53 CLIENT.discovered_api(42)
54 end).to raise_error(TypeError)
57 it 'should raise an error for bogus services' do
59 CLIENT.preferred_version(42)
60 end).to raise_error(TypeError)
63 it 'should raise an error for bogus methods' do
66 end).to raise_error(TypeError)
69 it 'should not return a preferred version for bogus service names' do
70 expect(CLIENT.preferred_version('bogus')).to eq(nil)
73 describe 'with the prediction API' do
75 CLIENT.authorization = nil
76 # The prediction API no longer exposes a v1, so we have to be
77 # careful about looking up the wrong API version.
78 @prediction = CLIENT.discovered_api('prediction', 'v1.2')
81 it 'should correctly determine the discovery URI' do
82 expect(CLIENT.discovery_uri('prediction')).to be ===
83 'https://www.googleapis.com/discovery/v1/apis/prediction/v1/rest'
86 it 'should correctly determine the discovery URI if :user_ip is set' do
87 CLIENT.user_ip = '127.0.0.1'
89 conn = stub_connection do |stub|
90 stub.get('/discovery/v1/apis/prediction/v1.2/rest?userIp=127.0.0.1') do |env|
95 :http_method => 'GET',
96 :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
97 :authenticated => false,
103 it 'should correctly determine the discovery URI if :key is set' do
104 CLIENT.key = 'qwerty'
105 conn = stub_connection do |stub|
106 stub.get('/discovery/v1/apis/prediction/v1.2/rest?key=qwerty') do |env|
110 request = CLIENT.execute(
111 :http_method => 'GET',
112 :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
113 :authenticated => false,
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|
127 request = CLIENT.execute(
128 :http_method => 'GET',
129 :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
130 :authenticated => false,
136 it 'should correctly generate API objects' do
137 expect(CLIENT.discovered_api('prediction', 'v1.2').name).to eq('prediction')
138 expect(CLIENT.discovered_api('prediction', 'v1.2').version).to eq('v1.2')
139 expect(CLIENT.discovered_api(:prediction, 'v1.2').name).to eq('prediction')
140 expect(CLIENT.discovered_api(:prediction, 'v1.2').version).to eq('v1.2')
143 it 'should discover methods' do
144 expect(CLIENT.discovered_method(
145 'prediction.training.insert', 'prediction', 'v1.2'
146 ).name).to eq('insert')
147 expect(CLIENT.discovered_method(
148 :'prediction.training.insert', :prediction, 'v1.2'
149 ).name).to eq('insert')
150 expect(CLIENT.discovered_method(
151 'prediction.training.delete', 'prediction', 'v1.2'
152 ).name).to eq('delete')
155 it 'should define the origin API in discovered methods' do
156 expect(CLIENT.discovered_method(
157 'prediction.training.insert', 'prediction', 'v1.2'
158 ).api.name).to eq('prediction')
161 it 'should not find methods that are not in the discovery document' do
162 expect(CLIENT.discovered_method(
163 'prediction.bogus', 'prediction', 'v1.2'
167 it 'should raise an error for bogus methods' do
169 CLIENT.discovered_method(42, 'prediction', 'v1.2')
170 end).to raise_error(TypeError)
173 it 'should raise an error for bogus methods' do
175 CLIENT.execute(:api_method => CLIENT.discovered_api('prediction', 'v1.2'))
176 end).to raise_error(TypeError)
179 it 'should correctly determine the preferred version' do
180 expect(CLIENT.preferred_version('prediction').version).not_to eq('v1')
181 expect(CLIENT.preferred_version(:prediction).version).not_to eq('v1')
184 it 'should return a batch path' do
185 expect(CLIENT.discovered_api('prediction', 'v1.2').batch_path).not_to be_nil
188 it 'should generate valid requests' do
189 conn = stub_connection do |stub|
190 stub.post('/prediction/v1.2/training?data=12345') do |env|
191 expect(env[:body]).to eq('')
195 request = CLIENT.execute(
196 :api_method => @prediction.training.insert,
197 :parameters => {'data' => '12345'},
203 it 'should generate valid requests when parameter value includes semicolon' do
204 conn = stub_connection do |stub|
205 # semicolon (;) in parameter value was being converted to
206 # bare ampersand (&) in 0.4.7. ensure that it gets converted
207 # to a CGI-escaped semicolon (%3B) instead.
208 stub.post('/prediction/v1.2/training?data=12345%3B67890') do |env|
209 expect(env[:body]).to eq('')
213 request = CLIENT.execute(
214 :api_method => @prediction.training.insert,
215 :parameters => {'data' => '12345;67890'},
221 it 'should generate valid requests when multivalued parameters are passed' do
222 conn = stub_connection do |stub|
223 stub.post('/prediction/v1.2/training?data=1&data=2') do |env|
224 expect(env.params['data']).to include('1', '2')
228 request = CLIENT.execute(
229 :api_method => @prediction.training.insert,
230 :parameters => {'data' => ['1', '2']},
236 it 'should generate requests against the correct URIs' do
237 conn = stub_connection do |stub|
238 stub.post('/prediction/v1.2/training?data=12345') do |env|
242 request = CLIENT.execute(
243 :api_method => @prediction.training.insert,
244 :parameters => {'data' => '12345'},
250 it 'should generate requests against the correct URIs' do
251 conn = stub_connection do |stub|
252 stub.post('/prediction/v1.2/training?data=12345') do |env|
256 request = CLIENT.execute(
257 :api_method => @prediction.training.insert,
258 :parameters => {'data' => '12345'},
264 it 'should allow modification to the base URIs for testing purposes' do
265 # Using a new client instance here to avoid caching rebased discovery doc
267 Google::APIClient.new(:application_name => 'API Client Tests').discovered_api('prediction', 'v1.2')
268 prediction_rebase.method_base =
269 'https://testing-domain.example.com/prediction/v1.2/'
271 conn = stub_connection do |stub|
272 stub.post('/prediction/v1.2/training') do |env|
273 expect(env[:url].host).to eq('testing-domain.example.com')
278 request = CLIENT.execute(
279 :api_method => prediction_rebase.training.insert,
280 :parameters => {'data' => '123'},
286 it 'should generate OAuth 1 requests' do
287 CLIENT.authorization = :oauth_1
288 CLIENT.authorization.token_credential_key = '12345'
289 CLIENT.authorization.token_credential_secret = '12345'
291 conn = stub_connection do |stub|
292 stub.post('/prediction/v1.2/training?data=12345') do |env|
293 expect(env[:request_headers]).to have_key('Authorization')
294 expect(env[:request_headers]['Authorization']).to match(/^OAuth/)
299 request = CLIENT.execute(
300 :api_method => @prediction.training.insert,
301 :parameters => {'data' => '12345'},
307 it 'should generate OAuth 2 requests' do
308 CLIENT.authorization = :oauth_2
309 CLIENT.authorization.access_token = '12345'
311 conn = stub_connection do |stub|
312 stub.post('/prediction/v1.2/training?data=12345') do |env|
313 expect(env[:request_headers]).to have_key('Authorization')
314 expect(env[:request_headers]['Authorization']).to match(/^Bearer/)
319 request = CLIENT.execute(
320 :api_method => @prediction.training.insert,
321 :parameters => {'data' => '12345'},
327 it 'should not be able to execute improperly authorized requests' do
328 CLIENT.authorization = :oauth_1
329 CLIENT.authorization.token_credential_key = '12345'
330 CLIENT.authorization.token_credential_secret = '12345'
331 result = CLIENT.execute(
332 @prediction.training.insert,
335 expect(result.response.status).to eq(401)
338 it 'should not be able to execute improperly authorized requests' do
339 CLIENT.authorization = :oauth_2
340 CLIENT.authorization.access_token = '12345'
341 result = CLIENT.execute(
342 @prediction.training.insert,
345 expect(result.response.status).to eq(401)
348 it 'should not be able to execute improperly authorized requests' do
350 CLIENT.authorization = :oauth_1
351 CLIENT.authorization.token_credential_key = '12345'
352 CLIENT.authorization.token_credential_secret = '12345'
353 result = CLIENT.execute!(
354 @prediction.training.insert,
357 end).to raise_error(Google::APIClient::ClientError)
360 it 'should not be able to execute improperly authorized requests' do
362 CLIENT.authorization = :oauth_2
363 CLIENT.authorization.access_token = '12345'
364 result = CLIENT.execute!(
365 @prediction.training.insert,
368 end).to raise_error(Google::APIClient::ClientError)
371 it 'should correctly handle unnamed parameters' do
372 conn = stub_connection do |stub|
373 stub.post('/prediction/v1.2/training') do |env|
374 expect(env[:request_headers]).to have_key('Content-Type')
375 expect(env[:request_headers]['Content-Type']).to eq('application/json')
379 CLIENT.authorization = :oauth_2
380 CLIENT.authorization.access_token = '12345'
382 :api_method => @prediction.training.insert,
383 :body => MultiJson.dump({"id" => "bucket/object"}),
384 :headers => {'Content-Type' => 'application/json'},
391 describe 'with the plus API' do
393 CLIENT.authorization = nil
394 @plus = CLIENT.discovered_api('plus')
397 it 'should correctly determine the discovery URI' do
398 expect(CLIENT.discovery_uri('plus')).to be ===
399 'https://www.googleapis.com/discovery/v1/apis/plus/v1/rest'
402 it 'should find APIs that are in the discovery document' do
403 expect(CLIENT.discovered_api('plus').name).to eq('plus')
404 expect(CLIENT.discovered_api('plus').version).to eq('v1')
405 expect(CLIENT.discovered_api(:plus).name).to eq('plus')
406 expect(CLIENT.discovered_api(:plus).version).to eq('v1')
409 it 'should find methods that are in the discovery document' do
410 # TODO(bobaman) Fix this when the RPC names are correct
411 expect(CLIENT.discovered_method(
412 'plus.activities.list', 'plus'
413 ).name).to eq('list')
416 it 'should define the origin API in discovered methods' do
417 expect(CLIENT.discovered_method(
418 'plus.activities.list', 'plus'
419 ).api.name).to eq('plus')
422 it 'should not find methods that are not in the discovery document' do
423 expect(CLIENT.discovered_method('plus.bogus', 'plus')).to eq(nil)
426 it 'should generate requests against the correct URIs' do
427 conn = stub_connection do |stub|
428 stub.get('/plus/v1/people/107807692475771887386/activities/public') do |env|
433 request = CLIENT.execute(
434 :api_method => @plus.activities.list,
436 'userId' => '107807692475771887386', 'collection' => 'public'
438 :authenticated => false,
444 it 'should correctly validate parameters' do
447 :api_method => @plus.activities.list,
448 :parameters => {'alt' => 'json'},
449 :authenticated => false
451 end).to raise_error(ArgumentError)
454 it 'should correctly validate parameters' do
457 :api_method => @plus.activities.list,
459 'userId' => '107807692475771887386', 'collection' => 'bogus'
461 :authenticated => false
462 ).to_env(CLIENT.connection)
463 end).to raise_error(ArgumentError)
467 describe 'with the adsense API' do
469 CLIENT.authorization = nil
470 @adsense = CLIENT.discovered_api('adsense', 'v1.3')
473 it 'should correctly determine the discovery URI' do
474 expect(CLIENT.discovery_uri('adsense', 'v1.3').to_s).to be ===
475 'https://www.googleapis.com/discovery/v1/apis/adsense/v1.3/rest'
478 it 'should find APIs that are in the discovery document' do
479 expect(CLIENT.discovered_api('adsense', 'v1.3').name).to eq('adsense')
480 expect(CLIENT.discovered_api('adsense', 'v1.3').version).to eq('v1.3')
483 it 'should return a batch path' do
484 expect(CLIENT.discovered_api('adsense', 'v1.3').batch_path).not_to be_nil
487 it 'should find methods that are in the discovery document' do
488 expect(CLIENT.discovered_method(
489 'adsense.reports.generate', 'adsense', 'v1.3'
490 ).name).to eq('generate')
493 it 'should not find methods that are not in the discovery document' do
494 expect(CLIENT.discovered_method('adsense.bogus', 'adsense', 'v1.3')).to eq(nil)
497 it 'should generate requests against the correct URIs' do
498 conn = stub_connection do |stub|
499 stub.get('/adsense/v1.3/adclients') do |env|
503 request = CLIENT.execute(
504 :api_method => @adsense.adclients.list,
505 :authenticated => false,
511 it 'should not be able to execute requests without authorization' do
512 result = CLIENT.execute(
513 :api_method => @adsense.adclients.list,
514 :authenticated => false
516 expect(result.response.status).to eq(401)
519 it 'should fail when validating missing required parameters' do
522 :api_method => @adsense.reports.generate,
523 :authenticated => false
525 end).to raise_error(ArgumentError)
528 it 'should succeed when validating parameters in a correct call' do
529 conn = stub_connection do |stub|
530 stub.get('/adsense/v1.3/reports?dimension=DATE&endDate=2010-01-01&metric=PAGE_VIEWS&startDate=2000-01-01') do |env|
536 :api_method => @adsense.reports.generate,
538 'startDate' => '2000-01-01',
539 'endDate' => '2010-01-01',
540 'dimension' => 'DATE',
541 'metric' => 'PAGE_VIEWS'
543 :authenticated => false,
546 end).not_to raise_error
550 it 'should fail when validating parameters with invalid values' do
553 :api_method => @adsense.reports.generate,
555 'startDate' => '2000-01-01',
556 'endDate' => '2010-01-01',
557 'dimension' => 'BAD_CHARACTERS=-&*(£&',
558 'metric' => 'PAGE_VIEWS'
560 :authenticated => false
562 end).to raise_error(ArgumentError)
565 it 'should succeed when validating repeated parameters in a correct call' do
566 conn = stub_connection do |stub|
567 stub.get('/adsense/v1.3/reports?dimension=DATE&dimension=PRODUCT_CODE'+
568 '&endDate=2010-01-01&metric=CLICKS&metric=PAGE_VIEWS&'+
569 'startDate=2000-01-01') do |env|
575 :api_method => @adsense.reports.generate,
577 'startDate' => '2000-01-01',
578 'endDate' => '2010-01-01',
579 'dimension' => ['DATE', 'PRODUCT_CODE'],
580 'metric' => ['PAGE_VIEWS', 'CLICKS']
582 :authenticated => false,
585 end).not_to raise_error
589 it 'should fail when validating incorrect repeated parameters' do
592 :api_method => @adsense.reports.generate,
594 'startDate' => '2000-01-01',
595 'endDate' => '2010-01-01',
596 'dimension' => ['DATE', 'BAD_CHARACTERS=-&*(£&'],
597 'metric' => ['PAGE_VIEWS', 'CLICKS']
599 :authenticated => false
601 end).to raise_error(ArgumentError)
604 it 'should generate valid requests when multivalued parameters are passed' do
605 conn = stub_connection do |stub|
606 stub.get('/adsense/v1.3/reports?dimension=DATE&dimension=PRODUCT_CODE'+
607 '&endDate=2010-01-01&metric=CLICKS&metric=PAGE_VIEWS&'+
608 'startDate=2000-01-01') do |env|
609 expect(env.params['dimension']).to include('DATE', 'PRODUCT_CODE')
610 expect(env.params['metric']).to include('CLICKS', 'PAGE_VIEWS')
614 request = CLIENT.execute(
615 :api_method => @adsense.reports.generate,
617 'startDate' => '2000-01-01',
618 'endDate' => '2010-01-01',
619 'dimension' => ['DATE', 'PRODUCT_CODE'],
620 'metric' => ['PAGE_VIEWS', 'CLICKS']
622 :authenticated => false,
629 describe 'with the Drive API' do
631 CLIENT.authorization = nil
632 @drive = CLIENT.discovered_api('drive', 'v1')
635 it 'should include media upload info methods' do
636 expect(@drive.files.insert.media_upload).not_to eq(nil)
639 it 'should include accepted media types' do
640 expect(@drive.files.insert.media_upload.accepted_types).not_to be_empty
643 it 'should have an upload path' do
644 expect(@drive.files.insert.media_upload.uri_template).not_to eq(nil)
647 it 'should have a max file size' do
648 expect(@drive.files.insert.media_upload.max_size).not_to eq(nil)