jomz-google-api-client 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +144 -0
- data/CONTRIBUTING.md +32 -0
- data/Gemfile +41 -0
- data/LICENSE +202 -0
- data/README.md +192 -0
- data/Rakefile +46 -0
- data/lib/cacerts.pem +2183 -0
- data/lib/compat/multi_json.rb +16 -0
- data/lib/google/api_client.rb +672 -0
- data/lib/google/api_client/auth/compute_service_account.rb +28 -0
- data/lib/google/api_client/auth/file_storage.rb +87 -0
- data/lib/google/api_client/auth/installed_app.rb +122 -0
- data/lib/google/api_client/auth/jwt_asserter.rb +126 -0
- data/lib/google/api_client/auth/key_utils.rb +93 -0
- data/lib/google/api_client/auth/pkcs12.rb +41 -0
- data/lib/google/api_client/batch.rb +323 -0
- data/lib/google/api_client/client_secrets.rb +176 -0
- data/lib/google/api_client/discovery.rb +19 -0
- data/lib/google/api_client/discovery/api.rb +300 -0
- data/lib/google/api_client/discovery/media.rb +77 -0
- data/lib/google/api_client/discovery/method.rb +363 -0
- data/lib/google/api_client/discovery/resource.rb +156 -0
- data/lib/google/api_client/discovery/schema.rb +121 -0
- data/lib/google/api_client/environment.rb +42 -0
- data/lib/google/api_client/errors.rb +60 -0
- data/lib/google/api_client/gzip.rb +28 -0
- data/lib/google/api_client/logging.rb +32 -0
- data/lib/google/api_client/media.rb +259 -0
- data/lib/google/api_client/railtie.rb +16 -0
- data/lib/google/api_client/reference.rb +27 -0
- data/lib/google/api_client/request.rb +351 -0
- data/lib/google/api_client/result.rb +253 -0
- data/lib/google/api_client/service.rb +233 -0
- data/lib/google/api_client/service/batch.rb +103 -0
- data/lib/google/api_client/service/request.rb +144 -0
- data/lib/google/api_client/service/resource.rb +40 -0
- data/lib/google/api_client/service/result.rb +162 -0
- data/lib/google/api_client/service/simple_file_store.rb +151 -0
- data/lib/google/api_client/service/stub_generator.rb +59 -0
- data/lib/google/api_client/service_account.rb +18 -0
- data/lib/google/api_client/version.rb +31 -0
- data/lib/google/inflection.rb +28 -0
- data/spec/fixtures/files/privatekey.p12 +0 -0
- data/spec/fixtures/files/sample.txt +33 -0
- data/spec/fixtures/files/secret.pem +19 -0
- data/spec/google/api_client/batch_spec.rb +249 -0
- data/spec/google/api_client/discovery_spec.rb +652 -0
- data/spec/google/api_client/gzip_spec.rb +86 -0
- data/spec/google/api_client/media_spec.rb +179 -0
- data/spec/google/api_client/request_spec.rb +30 -0
- data/spec/google/api_client/result_spec.rb +203 -0
- data/spec/google/api_client/service_account_spec.rb +164 -0
- data/spec/google/api_client/service_spec.rb +586 -0
- data/spec/google/api_client/simple_file_store_spec.rb +137 -0
- data/spec/google/api_client_spec.rb +253 -0
- data/spec/spec_helper.rb +56 -0
- data/tasks/gem.rake +97 -0
- data/tasks/git.rake +45 -0
- data/tasks/metrics.rake +22 -0
- data/tasks/spec.rake +57 -0
- data/tasks/wiki.rake +82 -0
- data/tasks/yard.rake +29 -0
- metadata +309 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
# Copyright 2012 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 'google/api_client'
|
18
|
+
|
19
|
+
fixtures_path = File.expand_path('../../../fixtures', __FILE__)
|
20
|
+
|
21
|
+
describe Google::APIClient::KeyUtils do
|
22
|
+
it 'should read PKCS12 files from the filesystem' do
|
23
|
+
pending "Reading from PKCS12 not supported on jruby" if RUBY_PLATFORM == 'java'
|
24
|
+
path = File.expand_path('files/privatekey.p12', fixtures_path)
|
25
|
+
key = Google::APIClient::KeyUtils.load_from_pkcs12(path, 'notasecret')
|
26
|
+
key.should_not == nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should read PKCS12 files from loaded files' do
|
30
|
+
pending "Reading from PKCS12 not supported on jruby" if RUBY_PLATFORM == 'java'
|
31
|
+
path = File.expand_path('files/privatekey.p12', fixtures_path)
|
32
|
+
content = File.read(path)
|
33
|
+
key = Google::APIClient::KeyUtils.load_from_pkcs12(content, 'notasecret')
|
34
|
+
key.should_not == nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should read PEM files from the filesystem' do
|
38
|
+
path = File.expand_path('files/secret.pem', fixtures_path)
|
39
|
+
key = Google::APIClient::KeyUtils.load_from_pem(path, 'notasecret')
|
40
|
+
key.should_not == nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should read PEM files from loaded files' do
|
44
|
+
path = File.expand_path('files/secret.pem', fixtures_path)
|
45
|
+
content = File.read(path)
|
46
|
+
key = Google::APIClient::KeyUtils.load_from_pem(content, 'notasecret')
|
47
|
+
key.should_not == nil
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe Google::APIClient::JWTAsserter do
|
53
|
+
include ConnectionHelpers
|
54
|
+
|
55
|
+
before do
|
56
|
+
@key = OpenSSL::PKey::RSA.new 2048
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should generate valid JWTs' do
|
60
|
+
asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
|
61
|
+
jwt = asserter.to_authorization.to_jwt
|
62
|
+
jwt.should_not == nil
|
63
|
+
|
64
|
+
claim = JWT.decode(jwt, @key.public_key, true)
|
65
|
+
claim["iss"].should == 'client1'
|
66
|
+
claim["scope"].should == 'scope1 scope2'
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should allow impersonation' do
|
70
|
+
conn = stub_connection do |stub|
|
71
|
+
stub.post('/o/oauth2/token') do |env|
|
72
|
+
params = Addressable::URI.form_unencode(env[:body])
|
73
|
+
JWT.decode(params.assoc("assertion").last, @key.public_key)
|
74
|
+
params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
|
75
|
+
[200, {}, '{
|
76
|
+
"access_token" : "1/abcdef1234567890",
|
77
|
+
"token_type" : "Bearer",
|
78
|
+
"expires_in" : 3600
|
79
|
+
}']
|
80
|
+
end
|
81
|
+
end
|
82
|
+
asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
|
83
|
+
auth = asserter.authorize('user1@email.com', { :connection => conn })
|
84
|
+
auth.should_not == nil?
|
85
|
+
auth.person.should == 'user1@email.com'
|
86
|
+
conn.verify
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should send valid access token request' do
|
90
|
+
conn = stub_connection do |stub|
|
91
|
+
stub.post('/o/oauth2/token') do |env|
|
92
|
+
params = Addressable::URI.form_unencode(env[:body])
|
93
|
+
JWT.decode(params.assoc("assertion").last, @key.public_key)
|
94
|
+
params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
|
95
|
+
[200, {}, '{
|
96
|
+
"access_token" : "1/abcdef1234567890",
|
97
|
+
"token_type" : "Bearer",
|
98
|
+
"expires_in" : 3600
|
99
|
+
}']
|
100
|
+
end
|
101
|
+
end
|
102
|
+
asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
|
103
|
+
auth = asserter.authorize(nil, { :connection => conn })
|
104
|
+
auth.should_not == nil?
|
105
|
+
auth.access_token.should == "1/abcdef1234567890"
|
106
|
+
conn.verify
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should be refreshable' do
|
110
|
+
conn = stub_connection do |stub|
|
111
|
+
stub.post('/o/oauth2/token') do |env|
|
112
|
+
params = Addressable::URI.form_unencode(env[:body])
|
113
|
+
JWT.decode(params.assoc("assertion").last, @key.public_key)
|
114
|
+
params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
|
115
|
+
[200, {}, '{
|
116
|
+
"access_token" : "1/abcdef1234567890",
|
117
|
+
"token_type" : "Bearer",
|
118
|
+
"expires_in" : 3600
|
119
|
+
}']
|
120
|
+
end
|
121
|
+
stub.post('/o/oauth2/token') do |env|
|
122
|
+
params = Addressable::URI.form_unencode(env[:body])
|
123
|
+
JWT.decode(params.assoc("assertion").last, @key.public_key)
|
124
|
+
params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
|
125
|
+
[200, {}, '{
|
126
|
+
"access_token" : "1/0987654321fedcba",
|
127
|
+
"token_type" : "Bearer",
|
128
|
+
"expires_in" : 3600
|
129
|
+
}']
|
130
|
+
end
|
131
|
+
end
|
132
|
+
asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
|
133
|
+
auth = asserter.authorize(nil, { :connection => conn })
|
134
|
+
auth.should_not == nil?
|
135
|
+
auth.access_token.should == "1/abcdef1234567890"
|
136
|
+
|
137
|
+
auth.fetch_access_token!(:connection => conn)
|
138
|
+
auth.access_token.should == "1/0987654321fedcba"
|
139
|
+
|
140
|
+
conn.verify
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe Google::APIClient::ComputeServiceAccount do
|
145
|
+
include ConnectionHelpers
|
146
|
+
|
147
|
+
it 'should query metadata server' do
|
148
|
+
conn = stub_connection do |stub|
|
149
|
+
stub.get('/computeMetadata/v1beta1/instance/service-accounts/default/token') do |env|
|
150
|
+
env.url.host.should == 'metadata'
|
151
|
+
[200, {}, '{
|
152
|
+
"access_token" : "1/abcdef1234567890",
|
153
|
+
"token_type" : "Bearer",
|
154
|
+
"expires_in" : 3600
|
155
|
+
}']
|
156
|
+
end
|
157
|
+
end
|
158
|
+
service_account = Google::APIClient::ComputeServiceAccount.new
|
159
|
+
auth = service_account.fetch_access_token!({ :connection => conn })
|
160
|
+
auth.should_not == nil?
|
161
|
+
auth["access_token"].should == "1/abcdef1234567890"
|
162
|
+
conn.verify
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,586 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
|
3
|
+
# Copyright 2013 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
|
+
require 'spec_helper'
|
18
|
+
|
19
|
+
require 'google/api_client'
|
20
|
+
require 'google/api_client/service'
|
21
|
+
|
22
|
+
fixtures_path = File.expand_path('../../../fixtures', __FILE__)
|
23
|
+
|
24
|
+
describe Google::APIClient::Service do
|
25
|
+
include ConnectionHelpers
|
26
|
+
|
27
|
+
APPLICATION_NAME = 'API Client Tests'
|
28
|
+
|
29
|
+
it 'should error out when called without an API name or version' do
|
30
|
+
(lambda do
|
31
|
+
Google::APIClient::Service.new
|
32
|
+
end).should raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should error out when called without an API version' do
|
36
|
+
(lambda do
|
37
|
+
Google::APIClient::Service.new('foo')
|
38
|
+
end).should raise_error(ArgumentError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should error out when the options hash is not a hash' do
|
42
|
+
(lambda do
|
43
|
+
Google::APIClient::Service.new('foo', 'v1', 42)
|
44
|
+
end).should raise_error(ArgumentError)
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'with the AdSense Management API' do
|
48
|
+
|
49
|
+
it 'should make a valid call for a method with no parameters' do
|
50
|
+
conn = stub_connection do |stub|
|
51
|
+
stub.get('/adsense/v1.3/adclients') do |env|
|
52
|
+
[200, {}, '{}']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
adsense = Google::APIClient::Service.new(
|
56
|
+
'adsense',
|
57
|
+
'v1.3',
|
58
|
+
{
|
59
|
+
:application_name => APPLICATION_NAME,
|
60
|
+
:authenticated => false,
|
61
|
+
:connection => conn,
|
62
|
+
:cache_store => nil
|
63
|
+
}
|
64
|
+
)
|
65
|
+
|
66
|
+
req = adsense.adclients.list.execute()
|
67
|
+
conn.verify
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should make a valid call for a method with parameters' do
|
71
|
+
conn = stub_connection do |stub|
|
72
|
+
stub.get('/adsense/v1.3/adclients/1/adunits') do |env|
|
73
|
+
[200, {}, '{}']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
adsense = Google::APIClient::Service.new(
|
77
|
+
'adsense',
|
78
|
+
'v1.3',
|
79
|
+
{
|
80
|
+
:application_name => APPLICATION_NAME,
|
81
|
+
:authenticated => false,
|
82
|
+
:connection => conn,
|
83
|
+
:cache_store => nil
|
84
|
+
}
|
85
|
+
)
|
86
|
+
req = adsense.adunits.list(:adClientId => '1').execute()
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should make a valid call for a deep method' do
|
90
|
+
conn = stub_connection do |stub|
|
91
|
+
stub.get('/adsense/v1.3/accounts/1/adclients') do |env|
|
92
|
+
[200, {}, '{}']
|
93
|
+
end
|
94
|
+
end
|
95
|
+
adsense = Google::APIClient::Service.new(
|
96
|
+
'adsense',
|
97
|
+
'v1.3',
|
98
|
+
{
|
99
|
+
:application_name => APPLICATION_NAME,
|
100
|
+
:authenticated => false,
|
101
|
+
:connection => conn,
|
102
|
+
:cache_store => nil
|
103
|
+
}
|
104
|
+
)
|
105
|
+
req = adsense.accounts.adclients.list(:accountId => '1').execute()
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'with no connection' do
|
109
|
+
before do
|
110
|
+
@adsense = Google::APIClient::Service.new('adsense', 'v1.3',
|
111
|
+
{:application_name => APPLICATION_NAME, :cache_store => nil})
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should return a resource when using a valid resource name' do
|
115
|
+
@adsense.accounts.should be_a(Google::APIClient::Service::Resource)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should throw an error when using an invalid resource name' do
|
119
|
+
(lambda do
|
120
|
+
@adsense.invalid_resource
|
121
|
+
end).should raise_error
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should return a request when using a valid method name' do
|
125
|
+
req = @adsense.adclients.list
|
126
|
+
req.should be_a(Google::APIClient::Service::Request)
|
127
|
+
req.method.id.should == 'adsense.adclients.list'
|
128
|
+
req.parameters.should be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should throw an error when using an invalid method name' do
|
132
|
+
(lambda do
|
133
|
+
@adsense.adclients.invalid_method
|
134
|
+
end).should raise_error
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should return a valid request with parameters' do
|
138
|
+
req = @adsense.adunits.list(:adClientId => '1')
|
139
|
+
req.should be_a(Google::APIClient::Service::Request)
|
140
|
+
req.method.id.should == 'adsense.adunits.list'
|
141
|
+
req.parameters.should_not be_nil
|
142
|
+
req.parameters[:adClientId].should == '1'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'with the Prediction API' do
|
148
|
+
|
149
|
+
it 'should make a valid call with an object body' do
|
150
|
+
conn = stub_connection do |stub|
|
151
|
+
stub.post('/prediction/v1.5/trainedmodels?project=1') do |env|
|
152
|
+
env.body.should == '{"id":"1"}'
|
153
|
+
[200, {}, '{}']
|
154
|
+
end
|
155
|
+
end
|
156
|
+
prediction = Google::APIClient::Service.new(
|
157
|
+
'prediction',
|
158
|
+
'v1.5',
|
159
|
+
{
|
160
|
+
:application_name => APPLICATION_NAME,
|
161
|
+
:authenticated => false,
|
162
|
+
:connection => conn,
|
163
|
+
:cache_store => nil
|
164
|
+
}
|
165
|
+
)
|
166
|
+
req = prediction.trainedmodels.insert(:project => '1').body({'id' => '1'}).execute()
|
167
|
+
conn.verify
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should make a valid call with a text body' do
|
171
|
+
conn = stub_connection do |stub|
|
172
|
+
stub.post('/prediction/v1.5/trainedmodels?project=1') do |env|
|
173
|
+
env.body.should == '{"id":"1"}'
|
174
|
+
[200, {}, '{}']
|
175
|
+
end
|
176
|
+
end
|
177
|
+
prediction = Google::APIClient::Service.new(
|
178
|
+
'prediction',
|
179
|
+
'v1.5',
|
180
|
+
{
|
181
|
+
:application_name => APPLICATION_NAME,
|
182
|
+
:authenticated => false,
|
183
|
+
:connection => conn,
|
184
|
+
:cache_store => nil
|
185
|
+
}
|
186
|
+
)
|
187
|
+
req = prediction.trainedmodels.insert(:project => '1').body('{"id":"1"}').execute()
|
188
|
+
conn.verify
|
189
|
+
end
|
190
|
+
|
191
|
+
describe 'with no connection' do
|
192
|
+
before do
|
193
|
+
@prediction = Google::APIClient::Service.new('prediction', 'v1.5',
|
194
|
+
{:application_name => APPLICATION_NAME, :cache_store => nil})
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should return a valid request with a body' do
|
198
|
+
req = @prediction.trainedmodels.insert(:project => '1').body({'id' => '1'})
|
199
|
+
req.should be_a(Google::APIClient::Service::Request)
|
200
|
+
req.method.id.should == 'prediction.trainedmodels.insert'
|
201
|
+
req.body.should == {'id' => '1'}
|
202
|
+
req.parameters.should_not be_nil
|
203
|
+
req.parameters[:project].should == '1'
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should return a valid request with a body when using resource name' do
|
207
|
+
req = @prediction.trainedmodels.insert(:project => '1').training({'id' => '1'})
|
208
|
+
req.should be_a(Google::APIClient::Service::Request)
|
209
|
+
req.method.id.should == 'prediction.trainedmodels.insert'
|
210
|
+
req.training.should == {'id' => '1'}
|
211
|
+
req.parameters.should_not be_nil
|
212
|
+
req.parameters[:project].should == '1'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe 'with the Drive API' do
|
218
|
+
|
219
|
+
before do
|
220
|
+
@metadata = {
|
221
|
+
'title' => 'My movie',
|
222
|
+
'description' => 'The best home movie ever made'
|
223
|
+
}
|
224
|
+
@file = File.expand_path('files/sample.txt', fixtures_path)
|
225
|
+
@media = Google::APIClient::UploadIO.new(@file, 'text/plain')
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'should make a valid call with an object body and media upload' do
|
229
|
+
conn = stub_connection do |stub|
|
230
|
+
stub.post('/upload/drive/v1/files?uploadType=multipart') do |env|
|
231
|
+
env.body.should be_a Faraday::CompositeReadIO
|
232
|
+
[200, {}, '{}']
|
233
|
+
end
|
234
|
+
end
|
235
|
+
drive = Google::APIClient::Service.new(
|
236
|
+
'drive',
|
237
|
+
'v1',
|
238
|
+
{
|
239
|
+
:application_name => APPLICATION_NAME,
|
240
|
+
:authenticated => false,
|
241
|
+
:connection => conn,
|
242
|
+
:cache_store => nil
|
243
|
+
}
|
244
|
+
)
|
245
|
+
req = drive.files.insert(:uploadType => 'multipart').body(@metadata).media(@media).execute()
|
246
|
+
conn.verify
|
247
|
+
end
|
248
|
+
|
249
|
+
describe 'with no connection' do
|
250
|
+
before do
|
251
|
+
@drive = Google::APIClient::Service.new('drive', 'v1',
|
252
|
+
{:application_name => APPLICATION_NAME, :cache_store => nil})
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should return a valid request with a body and media upload' do
|
256
|
+
req = @drive.files.insert(:uploadType => 'multipart').body(@metadata).media(@media)
|
257
|
+
req.should be_a(Google::APIClient::Service::Request)
|
258
|
+
req.method.id.should == 'drive.files.insert'
|
259
|
+
req.body.should == @metadata
|
260
|
+
req.media.should == @media
|
261
|
+
req.parameters.should_not be_nil
|
262
|
+
req.parameters[:uploadType].should == 'multipart'
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'should return a valid request with a body and media upload when using resource name' do
|
266
|
+
req = @drive.files.insert(:uploadType => 'multipart').file(@metadata).media(@media)
|
267
|
+
req.should be_a(Google::APIClient::Service::Request)
|
268
|
+
req.method.id.should == 'drive.files.insert'
|
269
|
+
req.file.should == @metadata
|
270
|
+
req.media.should == @media
|
271
|
+
req.parameters.should_not be_nil
|
272
|
+
req.parameters[:uploadType].should == 'multipart'
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe 'with the Discovery API' do
|
278
|
+
it 'should make a valid end-to-end request' do
|
279
|
+
discovery = Google::APIClient::Service.new('discovery', 'v1',
|
280
|
+
{:application_name => APPLICATION_NAME, :authenticated => false,
|
281
|
+
:cache_store => nil})
|
282
|
+
result = discovery.apis.get_rest(:api => 'discovery', :version => 'v1').execute
|
283
|
+
result.should_not be_nil
|
284
|
+
result.data.name.should == 'discovery'
|
285
|
+
result.data.version.should == 'v1'
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
|
291
|
+
describe Google::APIClient::Service::Result do
|
292
|
+
|
293
|
+
describe 'with the plus API' do
|
294
|
+
before do
|
295
|
+
@plus = Google::APIClient::Service.new('plus', 'v1',
|
296
|
+
{:application_name => APPLICATION_NAME, :cache_store => nil})
|
297
|
+
@reference = Google::APIClient::Reference.new({
|
298
|
+
:api_method => @plus.activities.list.method,
|
299
|
+
:parameters => {
|
300
|
+
'userId' => 'me',
|
301
|
+
'collection' => 'public',
|
302
|
+
'maxResults' => 20
|
303
|
+
}
|
304
|
+
})
|
305
|
+
@request = @plus.activities.list(:userId => 'me', :collection => 'public',
|
306
|
+
:maxResults => 20)
|
307
|
+
|
308
|
+
# Response double
|
309
|
+
@response = double("response")
|
310
|
+
@response.stub(:status).and_return(200)
|
311
|
+
@response.stub(:headers).and_return({
|
312
|
+
'etag' => '12345',
|
313
|
+
'x-google-apiary-auth-scopes' =>
|
314
|
+
'https://www.googleapis.com/auth/plus.me',
|
315
|
+
'content-type' => 'application/json; charset=UTF-8',
|
316
|
+
'date' => 'Mon, 23 Apr 2012 00:00:00 GMT',
|
317
|
+
'cache-control' => 'private, max-age=0, must-revalidate, no-transform',
|
318
|
+
'server' => 'GSE',
|
319
|
+
'connection' => 'close'
|
320
|
+
})
|
321
|
+
end
|
322
|
+
|
323
|
+
describe 'with a next page token' do
|
324
|
+
before do
|
325
|
+
@body = <<-END_OF_STRING
|
326
|
+
{
|
327
|
+
"kind": "plus#activityFeed",
|
328
|
+
"etag": "FOO",
|
329
|
+
"nextPageToken": "NEXT+PAGE+TOKEN",
|
330
|
+
"selfLink": "https://www.googleapis.com/plus/v1/people/foo/activities/public?",
|
331
|
+
"nextLink": "https://www.googleapis.com/plus/v1/people/foo/activities/public?maxResults=20&pageToken=NEXT%2BPAGE%2BTOKEN",
|
332
|
+
"title": "Plus Public Activity Feed for ",
|
333
|
+
"updated": "2012-04-23T00:00:00.000Z",
|
334
|
+
"id": "123456790",
|
335
|
+
"items": []
|
336
|
+
}
|
337
|
+
END_OF_STRING
|
338
|
+
@response.stub(:body).and_return(@body)
|
339
|
+
base_result = Google::APIClient::Result.new(@reference, @response)
|
340
|
+
@result = Google::APIClient::Service::Result.new(@request, base_result)
|
341
|
+
end
|
342
|
+
|
343
|
+
it 'should indicate a successful response' do
|
344
|
+
@result.error?.should be_false
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'should return the correct next page token' do
|
348
|
+
@result.next_page_token.should == 'NEXT+PAGE+TOKEN'
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'generate a correct request when calling next_page' do
|
352
|
+
next_page_request = @result.next_page
|
353
|
+
next_page_request.parameters.should include('pageToken')
|
354
|
+
next_page_request.parameters['pageToken'].should == 'NEXT+PAGE+TOKEN'
|
355
|
+
@request.parameters.each_pair do |param, value|
|
356
|
+
next_page_request.parameters[param].should == value
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'should return content type correctly' do
|
361
|
+
@result.media_type.should == 'application/json'
|
362
|
+
end
|
363
|
+
|
364
|
+
it 'should return the body correctly' do
|
365
|
+
@result.body.should == @body
|
366
|
+
end
|
367
|
+
|
368
|
+
it 'should return the result data correctly' do
|
369
|
+
@result.data?.should be_true
|
370
|
+
@result.data.class.to_s.should ==
|
371
|
+
'Google::APIClient::Schema::Plus::V1::ActivityFeed'
|
372
|
+
@result.data.kind.should == 'plus#activityFeed'
|
373
|
+
@result.data.etag.should == 'FOO'
|
374
|
+
@result.data.nextPageToken.should == 'NEXT+PAGE+TOKEN'
|
375
|
+
@result.data.selfLink.should ==
|
376
|
+
'https://www.googleapis.com/plus/v1/people/foo/activities/public?'
|
377
|
+
@result.data.nextLink.should ==
|
378
|
+
'https://www.googleapis.com/plus/v1/people/foo/activities/public?' +
|
379
|
+
'maxResults=20&pageToken=NEXT%2BPAGE%2BTOKEN'
|
380
|
+
@result.data.title.should == 'Plus Public Activity Feed for '
|
381
|
+
@result.data.id.should == "123456790"
|
382
|
+
@result.data.items.should be_empty
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
describe 'without a next page token' do
|
387
|
+
before do
|
388
|
+
@body = <<-END_OF_STRING
|
389
|
+
{
|
390
|
+
"kind": "plus#activityFeed",
|
391
|
+
"etag": "FOO",
|
392
|
+
"selfLink": "https://www.googleapis.com/plus/v1/people/foo/activities/public?",
|
393
|
+
"title": "Plus Public Activity Feed for ",
|
394
|
+
"updated": "2012-04-23T00:00:00.000Z",
|
395
|
+
"id": "123456790",
|
396
|
+
"items": []
|
397
|
+
}
|
398
|
+
END_OF_STRING
|
399
|
+
@response.stub(:body).and_return(@body)
|
400
|
+
base_result = Google::APIClient::Result.new(@reference, @response)
|
401
|
+
@result = Google::APIClient::Service::Result.new(@request, base_result)
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'should not return a next page token' do
|
405
|
+
@result.next_page_token.should == nil
|
406
|
+
end
|
407
|
+
|
408
|
+
it 'should return content type correctly' do
|
409
|
+
@result.media_type.should == 'application/json'
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'should return the body correctly' do
|
413
|
+
@result.body.should == @body
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'should return the result data correctly' do
|
417
|
+
@result.data?.should be_true
|
418
|
+
@result.data.class.to_s.should ==
|
419
|
+
'Google::APIClient::Schema::Plus::V1::ActivityFeed'
|
420
|
+
@result.data.kind.should == 'plus#activityFeed'
|
421
|
+
@result.data.etag.should == 'FOO'
|
422
|
+
@result.data.selfLink.should ==
|
423
|
+
'https://www.googleapis.com/plus/v1/people/foo/activities/public?'
|
424
|
+
@result.data.title.should == 'Plus Public Activity Feed for '
|
425
|
+
@result.data.id.should == "123456790"
|
426
|
+
@result.data.items.should be_empty
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
describe 'with JSON error response' do
|
431
|
+
before do
|
432
|
+
@body = <<-END_OF_STRING
|
433
|
+
{
|
434
|
+
"error": {
|
435
|
+
"errors": [
|
436
|
+
{
|
437
|
+
"domain": "global",
|
438
|
+
"reason": "parseError",
|
439
|
+
"message": "Parse Error"
|
440
|
+
}
|
441
|
+
],
|
442
|
+
"code": 400,
|
443
|
+
"message": "Parse Error"
|
444
|
+
}
|
445
|
+
}
|
446
|
+
END_OF_STRING
|
447
|
+
@response.stub(:body).and_return(@body)
|
448
|
+
@response.stub(:status).and_return(400)
|
449
|
+
base_result = Google::APIClient::Result.new(@reference, @response)
|
450
|
+
@result = Google::APIClient::Service::Result.new(@request, base_result)
|
451
|
+
end
|
452
|
+
|
453
|
+
it 'should return error status correctly' do
|
454
|
+
@result.error?.should be_true
|
455
|
+
end
|
456
|
+
|
457
|
+
it 'should return the correct error message' do
|
458
|
+
@result.error_message.should == 'Parse Error'
|
459
|
+
end
|
460
|
+
|
461
|
+
it 'should return the body correctly' do
|
462
|
+
@result.body.should == @body
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
describe 'with 204 No Content response' do
|
467
|
+
before do
|
468
|
+
@response.stub(:body).and_return('')
|
469
|
+
@response.stub(:status).and_return(204)
|
470
|
+
@response.stub(:headers).and_return({})
|
471
|
+
base_result = Google::APIClient::Result.new(@reference, @response)
|
472
|
+
@result = Google::APIClient::Service::Result.new(@request, base_result)
|
473
|
+
end
|
474
|
+
|
475
|
+
it 'should indicate no data is available' do
|
476
|
+
@result.data?.should be_false
|
477
|
+
end
|
478
|
+
|
479
|
+
it 'should return nil for data' do
|
480
|
+
@result.data.should == nil
|
481
|
+
end
|
482
|
+
|
483
|
+
it 'should return nil for media_type' do
|
484
|
+
@result.media_type.should == nil
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
describe Google::APIClient::Service::BatchRequest do
|
491
|
+
describe 'with the discovery API' do
|
492
|
+
before do
|
493
|
+
@discovery = Google::APIClient::Service.new('discovery', 'v1',
|
494
|
+
{:application_name => APPLICATION_NAME, :authorization => nil,
|
495
|
+
:cache_store => nil})
|
496
|
+
end
|
497
|
+
|
498
|
+
describe 'with two valid requests' do
|
499
|
+
before do
|
500
|
+
@calls = [
|
501
|
+
@discovery.apis.get_rest(:api => 'plus', :version => 'v1'),
|
502
|
+
@discovery.apis.get_rest(:api => 'discovery', :version => 'v1')
|
503
|
+
]
|
504
|
+
end
|
505
|
+
|
506
|
+
it 'should execute both when using a global callback' do
|
507
|
+
block_called = 0
|
508
|
+
batch = @discovery.batch(@calls) do |result|
|
509
|
+
block_called += 1
|
510
|
+
result.status.should == 200
|
511
|
+
end
|
512
|
+
|
513
|
+
batch.execute
|
514
|
+
block_called.should == 2
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'should execute both when using individual callbacks' do
|
518
|
+
call1_returned, call2_returned = false, false
|
519
|
+
batch = @discovery.batch
|
520
|
+
|
521
|
+
batch.add(@calls[0]) do |result|
|
522
|
+
call1_returned = true
|
523
|
+
result.status.should == 200
|
524
|
+
result.call_index.should == 0
|
525
|
+
end
|
526
|
+
|
527
|
+
batch.add(@calls[1]) do |result|
|
528
|
+
call2_returned = true
|
529
|
+
result.status.should == 200
|
530
|
+
result.call_index.should == 1
|
531
|
+
end
|
532
|
+
|
533
|
+
batch.execute
|
534
|
+
call1_returned.should == true
|
535
|
+
call2_returned.should == true
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
describe 'with a valid request and an invalid one' do
|
540
|
+
before do
|
541
|
+
@calls = [
|
542
|
+
@discovery.apis.get_rest(:api => 'plus', :version => 'v1'),
|
543
|
+
@discovery.apis.get_rest(:api => 'invalid', :version => 'invalid')
|
544
|
+
]
|
545
|
+
end
|
546
|
+
|
547
|
+
it 'should execute both when using a global callback' do
|
548
|
+
block_called = 0
|
549
|
+
batch = @discovery.batch(@calls) do |result|
|
550
|
+
block_called += 1
|
551
|
+
if result.call_index == 0
|
552
|
+
result.status.should == 200
|
553
|
+
else
|
554
|
+
result.status.should >= 400
|
555
|
+
result.status.should < 500
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
batch.execute
|
560
|
+
block_called.should == 2
|
561
|
+
end
|
562
|
+
|
563
|
+
it 'should execute both when using individual callbacks' do
|
564
|
+
call1_returned, call2_returned = false, false
|
565
|
+
batch = @discovery.batch
|
566
|
+
|
567
|
+
batch.add(@calls[0]) do |result|
|
568
|
+
call1_returned = true
|
569
|
+
result.status.should == 200
|
570
|
+
result.call_index.should == 0
|
571
|
+
end
|
572
|
+
|
573
|
+
batch.add(@calls[1]) do |result|
|
574
|
+
call2_returned = true
|
575
|
+
result.status.should >= 400
|
576
|
+
result.status.should < 500
|
577
|
+
result.call_index.should == 1
|
578
|
+
end
|
579
|
+
|
580
|
+
batch.execute
|
581
|
+
call1_returned.should == true
|
582
|
+
call2_returned.should == true
|
583
|
+
end
|
584
|
+
end
|
585
|
+
end
|
586
|
+
end
|