Updated rspec to v3 and replaced rcov with simplecov.
[arvados.git] / spec / google / api_client_spec.rb
1 # Copyright 2010 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 require 'spec_helper'
16
17 require 'faraday'
18 require 'signet/oauth_1/client'
19 require 'google/api_client'
20 require 'google/api_client/version'
21
22 shared_examples_for 'configurable user agent' do
23   include ConnectionHelpers
24   
25   it 'should allow the user agent to be modified' do
26     client.user_agent = 'Custom User Agent/1.2.3'
27     expect(client.user_agent).to eq('Custom User Agent/1.2.3')
28   end
29
30   it 'should allow the user agent to be set to nil' do
31     client.user_agent = nil
32     expect(client.user_agent).to eq(nil)
33   end
34
35   it 'should not allow the user agent to be used with bogus values' do
36     expect(lambda do
37       client.user_agent = 42
38       client.execute(:uri=>'https://www.google.com/')
39     end).to raise_error(TypeError)
40   end
41
42   it 'should transmit a User-Agent header when sending requests' do
43     client.user_agent = 'Custom User Agent/1.2.3'
44
45     conn = stub_connection do |stub|
46       stub.get('/') do |env|
47         headers = env[:request_headers]
48         expect(headers).to have_key('User-Agent')
49         expect(headers['User-Agent']).to eq(client.user_agent)
50         [200, {}, ['']]
51       end
52     end
53     client.execute(:uri=>'https://www.google.com/', :connection => conn)
54     conn.verify
55   end
56 end
57
58 describe Google::APIClient do
59   include ConnectionHelpers
60
61   let(:client) { Google::APIClient.new(:application_name => 'API Client Tests') }
62
63   it 'should make its version number available' do
64     expect(Google::APIClient::VERSION::STRING).to be_instance_of(String)
65   end
66
67   it 'should default to OAuth 2' do
68     expect(Signet::OAuth2::Client).to be === client.authorization
69   end
70
71   describe 'configure for no authentication' do
72     before do
73       client.authorization = nil
74     end
75     it_should_behave_like 'configurable user agent'
76   end
77     
78   describe 'configured for OAuth 1' do
79     before do
80       client.authorization = :oauth_1
81       client.authorization.token_credential_key = 'abc'
82       client.authorization.token_credential_secret = '123'
83     end
84
85     it 'should use the default OAuth1 client configuration' do
86       expect(client.authorization.temporary_credential_uri.to_s).to eq(
87         'https://www.google.com/accounts/OAuthGetRequestToken'
88       )
89       expect(client.authorization.authorization_uri.to_s).to include(
90         'https://www.google.com/accounts/OAuthAuthorizeToken'
91       )
92       expect(client.authorization.token_credential_uri.to_s).to eq(
93         'https://www.google.com/accounts/OAuthGetAccessToken'
94       )
95       expect(client.authorization.client_credential_key).to eq('anonymous')
96       expect(client.authorization.client_credential_secret).to eq('anonymous')
97     end
98
99     it_should_behave_like 'configurable user agent'
100   end
101
102   describe 'configured for OAuth 2' do
103     before do
104       client.authorization = :oauth_2
105       client.authorization.access_token = '12345'
106     end
107
108     # TODO
109     it_should_behave_like 'configurable user agent'
110   end
111   
112   describe 'when executing requests' do
113     before do
114       @prediction = client.discovered_api('prediction', 'v1.2')
115       client.authorization = :oauth_2
116       @connection = stub_connection do |stub|
117         stub.post('/prediction/v1.2/training?data=12345') do |env|
118           expect(env[:request_headers]['Authorization']).to eq('Bearer 12345')
119           [200, {}, '{}']
120         end
121       end
122     end
123
124     after do
125       @connection.verify
126     end
127     
128     it 'should use default authorization' do
129       client.authorization.access_token = "12345"
130       client.execute(  
131         :api_method => @prediction.training.insert,
132         :parameters => {'data' => '12345'},
133         :connection => @connection
134       )
135     end
136
137     it 'should use request scoped authorization when provided' do
138       client.authorization.access_token = "abcdef"
139       new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
140       client.execute(  
141         :api_method => @prediction.training.insert,
142         :parameters => {'data' => '12345'},
143         :authorization => new_auth,
144         :connection => @connection
145       )
146     end
147     
148     it 'should accept options with batch/request style execute' do
149       client.authorization.access_token = "abcdef"
150       new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
151       request = client.generate_request(
152         :api_method => @prediction.training.insert,
153         :parameters => {'data' => '12345'}
154       )
155       client.execute(
156         request,
157         :authorization => new_auth,
158         :connection => @connection
159       )
160     end
161     
162     
163     it 'should accept options in array style execute' do
164        client.authorization.access_token = "abcdef"
165        new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
166        client.execute(  
167          @prediction.training.insert, {'data' => '12345'}, '', {},
168          { :authorization => new_auth, :connection => @connection }         
169        )
170      end
171   end  
172
173   describe 'when retries enabled' do
174     before do
175       client.retries = 2
176     end
177
178     after do
179       @connection.verify
180     end
181     
182     it 'should follow redirects' do
183       client.authorization = nil
184       @connection = stub_connection do |stub|
185         stub.get('/foo') do |env|
186           [302, {'location' => 'https://www.google.com/bar'}, '{}']
187         end
188         stub.get('/bar') do |env|
189           [200, {}, '{}']
190         end
191       end
192
193       client.execute(  
194         :uri => 'https://www.gogole.com/foo',
195         :connection => @connection
196       )
197     end
198
199     it 'should refresh tokens on 401 tokens' do
200       client.authorization.access_token = '12345'
201       expect(client.authorization).to receive(:fetch_access_token!)
202
203       @connection = stub_connection do |stub|
204         stub.get('/foo') do |env|
205           [401, {}, '{}']
206         end
207         stub.get('/foo') do |env|
208           [200, {}, '{}']
209         end
210       end
211
212       client.execute(  
213         :uri => 'https://www.gogole.com/foo',
214         :connection => @connection
215       )
216     end
217
218
219     it 'should not attempt multiple token refreshes' do
220       client.authorization.access_token = '12345'
221       expect(client.authorization).to receive(:fetch_access_token!).once
222
223       @connection = stub_connection do |stub|
224         stub.get('/foo') do |env|
225           [401, {}, '{}']
226         end
227       end
228
229       client.execute(  
230         :uri => 'https://www.gogole.com/foo',
231         :connection => @connection
232       )
233     end
234
235     it 'should not retry on client errors' do
236       count = 0
237       @connection = stub_connection do |stub|
238         stub.get('/foo') do |env|
239           expect(count).to eq(0)
240           count += 1
241           [403, {}, '{}']
242         end
243       end
244
245       client.execute(  
246         :uri => 'https://www.gogole.com/foo',
247         :connection => @connection,
248         :authenticated => false
249       )
250     end
251
252     it 'should retry on 500 errors' do
253       client.authorization = nil
254
255       @connection = stub_connection do |stub|
256         stub.get('/foo') do |env|
257           [500, {}, '{}']
258         end
259         stub.get('/foo') do |env|
260           [200, {}, '{}']
261         end
262       end
263
264       expect(client.execute(  
265         :uri => 'https://www.gogole.com/foo',
266         :connection => @connection
267       ).status).to eq(200)
268
269     end
270
271     it 'should fail after max retries' do
272       client.authorization = nil
273       count = 0
274       @connection = stub_connection do |stub|
275         stub.get('/foo') do |env|
276           count += 1
277           [500, {}, '{}']
278         end
279       end
280
281       expect(client.execute(  
282         :uri => 'https://www.gogole.com/foo',
283         :connection => @connection
284       ).status).to eq(500)
285       expect(count).to eq(3)
286     end
287
288   end  
289 end