google-api-client 0.7.0.rc2 → 0.7.0

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.
@@ -0,0 +1,151 @@
1
+ # Copyright 2013 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
+ module Google
16
+ class APIClient
17
+ class Service
18
+
19
+ # Simple file store to be used in the event no ActiveSupport cache store
20
+ # is provided. This is not thread-safe, and does not support a number of
21
+ # features (such as expiration), but it's useful for the simple purpose of
22
+ # caching discovery documents to disk.
23
+ # Implements the basic cache methods of ActiveSupport::Cache::Store in a
24
+ # limited fashion.
25
+ class SimpleFileStore
26
+
27
+ # Creates a new SimpleFileStore.
28
+ #
29
+ # @param [String] file_path
30
+ # The path to the cache file on disk.
31
+ # @param [Object] options
32
+ # The options to be used with this SimpleFileStore. Not implemented.
33
+ def initialize(file_path, options = nil)
34
+ @file_path = file_path.to_s
35
+ end
36
+
37
+ # Returns true if a key exists in the cache.
38
+ #
39
+ # @param [String] name
40
+ # The name of the key. Will always be converted to a string.
41
+ # @param [Object] options
42
+ # The options to be used with this query. Not implemented.
43
+ def exist?(name, options = nil)
44
+ read_file
45
+ @cache.nil? ? nil : @cache.include?(name.to_s)
46
+ end
47
+
48
+ # Fetches data from the cache and returns it, using the given key.
49
+ # If the key is missing and no block is passed, returns nil.
50
+ # If the key is missing and a block is passed, executes the block, sets
51
+ # the key to its value, and returns it.
52
+ #
53
+ # @param [String] name
54
+ # The name of the key. Will always be converted to a string.
55
+ # @param [Object] options
56
+ # The options to be used with this query. Not implemented.
57
+ # @yield [String]
58
+ # optional block with the default value if the key is missing
59
+ def fetch(name, options = nil)
60
+ read_file
61
+ if block_given?
62
+ entry = read(name.to_s, options)
63
+ if entry.nil?
64
+ value = yield name.to_s
65
+ write(name.to_s, value)
66
+ return value
67
+ else
68
+ return entry
69
+ end
70
+ else
71
+ return read(name.to_s, options)
72
+ end
73
+ end
74
+
75
+ # Fetches data from the cache, using the given key.
76
+ # Returns nil if the key is missing.
77
+ #
78
+ # @param [String] name
79
+ # The name of the key. Will always be converted to a string.
80
+ # @param [Object] options
81
+ # The options to be used with this query. Not implemented.
82
+ def read(name, options = nil)
83
+ read_file
84
+ @cache.nil? ? nil : @cache[name.to_s]
85
+ end
86
+
87
+ # Writes the value to the cache, with the key.
88
+ #
89
+ # @param [String] name
90
+ # The name of the key. Will always be converted to a string.
91
+ # @param [Object] value
92
+ # The value to be written.
93
+ # @param [Object] options
94
+ # The options to be used with this query. Not implemented.
95
+ def write(name, value, options = nil)
96
+ read_file
97
+ @cache = {} if @cache.nil?
98
+ @cache[name.to_s] = value
99
+ write_file
100
+ return nil
101
+ end
102
+
103
+ # Deletes an entry in the cache.
104
+ # Returns true if an entry is deleted.
105
+ #
106
+ # @param [String] name
107
+ # The name of the key. Will always be converted to a string.
108
+ # @param [Object] options
109
+ # The options to be used with this query. Not implemented.
110
+ def delete(name, options = nil)
111
+ read_file
112
+ return nil if @cache.nil?
113
+ if @cache.include? name.to_s
114
+ @cache.delete name.to_s
115
+ write_file
116
+ return true
117
+ else
118
+ return nil
119
+ end
120
+ end
121
+
122
+ protected
123
+
124
+ # Read the entire cache file from disk.
125
+ # Will avoid reading if there have been no changes.
126
+ def read_file
127
+ if !File.exists? @file_path
128
+ @cache = nil
129
+ else
130
+ # Check for changes after our last read or write.
131
+ if @last_change.nil? || File.mtime(@file_path) > @last_change
132
+ File.open(@file_path) do |file|
133
+ @cache = Marshal.load(file)
134
+ @last_change = file.mtime
135
+ end
136
+ end
137
+ end
138
+ return @cache
139
+ end
140
+
141
+ # Write the entire cache contents to disk.
142
+ def write_file
143
+ File.open(@file_path, 'w') do |file|
144
+ Marshal.dump(@cache, file)
145
+ end
146
+ @last_change = File.mtime(@file_path)
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,59 @@
1
+ # Copyright 2013 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
+ module Google
16
+ class APIClient
17
+ class Service
18
+ ##
19
+ # Auxiliary mixin to generate resource and method stubs.
20
+ # Used by the Service and Service::Resource classes to generate both
21
+ # top-level and nested resources and methods.
22
+ module StubGenerator
23
+ def generate_call_stubs(service, root)
24
+ metaclass = (class << self; self; end)
25
+
26
+ # Handle resources.
27
+ root.discovered_resources.each do |resource|
28
+ method_name = Google::INFLECTOR.underscore(resource.name).to_sym
29
+ if !self.respond_to?(method_name)
30
+ metaclass.send(:define_method, method_name) do
31
+ Google::APIClient::Service::Resource.new(service, resource)
32
+ end
33
+ end
34
+ end
35
+
36
+ # Handle methods.
37
+ root.discovered_methods.each do |method|
38
+ method_name = Google::INFLECTOR.underscore(method.name).to_sym
39
+ if !self.respond_to?(method_name)
40
+ metaclass.send(:define_method, method_name) do |*args|
41
+ if args.length > 1
42
+ raise ArgumentError,
43
+ "wrong number of arguments (#{args.length} for 1)"
44
+ elsif !args.first.respond_to?(:to_hash) && !args.first.nil?
45
+ raise ArgumentError,
46
+ "expected parameter Hash, got #{args.first.class}"
47
+ else
48
+ return Google::APIClient::Service::Request.new(
49
+ service, method, args.first
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -23,7 +23,7 @@ if !defined?(::Google::APIClient::VERSION)
23
23
  MAJOR = 0
24
24
  MINOR = 7
25
25
  TINY = 0
26
- PATCH = 'rc2'
26
+ PATCH = nil
27
27
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
28
28
  end
29
29
  end
@@ -53,7 +53,7 @@ describe Google::APIClient::BatchRequest do
53
53
  @call1 = {
54
54
  :api_method => @discovery.apis.get_rest,
55
55
  :parameters => {
56
- 'api' => 'adsense',
56
+ 'api' => 'plus',
57
57
  'version' => 'v1'
58
58
  }
59
59
  }
@@ -118,7 +118,7 @@ describe Google::APIClient::BatchRequest do
118
118
  @call1 = {
119
119
  :api_method => @discovery.apis.get_rest,
120
120
  :parameters => {
121
- 'api' => 'adsense',
121
+ 'api' => 'plus',
122
122
  'version' => 'v1'
123
123
  }
124
124
  }
@@ -244,6 +244,6 @@ describe Google::APIClient::BatchRequest do
244
244
  #request[:body].read.gsub("\r", "").should =~ expected_body
245
245
  end
246
246
  end
247
-
247
+
248
248
  end
249
249
  end
@@ -86,9 +86,10 @@ describe Google::APIClient do
86
86
 
87
87
  it 'should correctly determine the discovery URI if :user_ip is set' do
88
88
  CLIENT.user_ip = '127.0.0.1'
89
-
89
+
90
90
  conn = stub_connection do |stub|
91
91
  stub.get('/discovery/v1/apis/prediction/v1.2/rest?userIp=127.0.0.1') do |env|
92
+ [200, {}, '{}']
92
93
  end
93
94
  end
94
95
  CLIENT.execute(
@@ -104,6 +105,7 @@ describe Google::APIClient do
104
105
  CLIENT.key = 'qwerty'
105
106
  conn = stub_connection do |stub|
106
107
  stub.get('/discovery/v1/apis/prediction/v1.2/rest?key=qwerty') do |env|
108
+ [200, {}, '{}']
107
109
  end
108
110
  end
109
111
  request = CLIENT.execute(
@@ -120,6 +122,7 @@ describe Google::APIClient do
120
122
  CLIENT.user_ip = '127.0.0.1'
121
123
  conn = stub_connection do |stub|
122
124
  stub.get('/discovery/v1/apis/prediction/v1.2/rest?key=qwerty&userIp=127.0.0.1') do |env|
125
+ [200, {}, '{}']
123
126
  end
124
127
  end
125
128
  request = CLIENT.execute(
@@ -187,6 +190,7 @@ describe Google::APIClient do
187
190
  conn = stub_connection do |stub|
188
191
  stub.post('/prediction/v1.2/training?data=12345') do |env|
189
192
  env[:body].should == ''
193
+ [200, {}, '{}']
190
194
  end
191
195
  end
192
196
  request = CLIENT.execute(
@@ -199,11 +203,12 @@ describe Google::APIClient do
199
203
 
200
204
  it 'should generate valid requests when parameter value includes semicolon' do
201
205
  conn = stub_connection do |stub|
202
- # semicolon (;) in parameter value was being converted to
203
- # bare ampersand (&) in 0.4.7. ensure that it gets converted
206
+ # semicolon (;) in parameter value was being converted to
207
+ # bare ampersand (&) in 0.4.7. ensure that it gets converted
204
208
  # to a CGI-escaped semicolon (%3B) instead.
205
209
  stub.post('/prediction/v1.2/training?data=12345%3B67890') do |env|
206
210
  env[:body].should == ''
211
+ [200, {}, '{}']
207
212
  end
208
213
  end
209
214
  request = CLIENT.execute(
@@ -218,6 +223,7 @@ describe Google::APIClient do
218
223
  conn = stub_connection do |stub|
219
224
  stub.post('/prediction/v1.2/training?data=1&data=2') do |env|
220
225
  env.params['data'].should include('1', '2')
226
+ [200, {}, '{}']
221
227
  end
222
228
  end
223
229
  request = CLIENT.execute(
@@ -231,6 +237,7 @@ describe Google::APIClient do
231
237
  it 'should generate requests against the correct URIs' do
232
238
  conn = stub_connection do |stub|
233
239
  stub.post('/prediction/v1.2/training?data=12345') do |env|
240
+ [200, {}, '{}']
234
241
  end
235
242
  end
236
243
  request = CLIENT.execute(
@@ -244,6 +251,7 @@ describe Google::APIClient do
244
251
  it 'should generate requests against the correct URIs' do
245
252
  conn = stub_connection do |stub|
246
253
  stub.post('/prediction/v1.2/training?data=12345') do |env|
254
+ [200, {}, '{}']
247
255
  end
248
256
  end
249
257
  request = CLIENT.execute(
@@ -264,9 +272,10 @@ describe Google::APIClient do
264
272
  conn = stub_connection do |stub|
265
273
  stub.post('/prediction/v1.2/training') do |env|
266
274
  env[:url].host.should == 'testing-domain.example.com'
275
+ [200, {}, '{}']
267
276
  end
268
277
  end
269
-
278
+
270
279
  request = CLIENT.execute(
271
280
  :api_method => prediction_rebase.training.insert,
272
281
  :parameters => {'data' => '123'},
@@ -284,6 +293,7 @@ describe Google::APIClient do
284
293
  stub.post('/prediction/v1.2/training?data=12345') do |env|
285
294
  env[:request_headers].should have_key('Authorization')
286
295
  env[:request_headers]['Authorization'].should =~ /^OAuth/
296
+ [200, {}, '{}']
287
297
  end
288
298
  end
289
299
 
@@ -303,6 +313,7 @@ describe Google::APIClient do
303
313
  stub.post('/prediction/v1.2/training?data=12345') do |env|
304
314
  env[:request_headers].should have_key('Authorization')
305
315
  env[:request_headers]['Authorization'].should =~ /^Bearer/
316
+ [200, {}, '{}']
306
317
  end
307
318
  end
308
319
 
@@ -363,6 +374,7 @@ describe Google::APIClient do
363
374
  stub.post('/prediction/v1.2/training') do |env|
364
375
  env[:request_headers].should have_key('Content-Type')
365
376
  env[:request_headers]['Content-Type'].should == 'application/json'
377
+ [200, {}, '{}']
366
378
  end
367
379
  end
368
380
  CLIENT.authorization = :oauth_2
@@ -415,9 +427,10 @@ describe Google::APIClient do
415
427
  it 'should generate requests against the correct URIs' do
416
428
  conn = stub_connection do |stub|
417
429
  stub.get('/plus/v1/people/107807692475771887386/activities/public') do |env|
430
+ [200, {}, '{}']
418
431
  end
419
432
  end
420
-
433
+
421
434
  request = CLIENT.execute(
422
435
  :api_method => @plus.activities.list,
423
436
  :parameters => {
@@ -474,17 +487,18 @@ describe Google::APIClient do
474
487
 
475
488
  it 'should find methods that are in the discovery document' do
476
489
  CLIENT.discovered_method(
477
- 'adsense.reports.generate', 'adsense'
490
+ 'adsense.reports.generate', 'adsense', 'v1.3'
478
491
  ).name.should == 'generate'
479
492
  end
480
493
 
481
494
  it 'should not find methods that are not in the discovery document' do
482
- CLIENT.discovered_method('adsense.bogus', 'adsense').should == nil
495
+ CLIENT.discovered_method('adsense.bogus', 'adsense', 'v1.3').should == nil
483
496
  end
484
497
 
485
498
  it 'should generate requests against the correct URIs' do
486
499
  conn = stub_connection do |stub|
487
500
  stub.get('/adsense/v1.3/adclients') do |env|
501
+ [200, {}, '{}']
488
502
  end
489
503
  end
490
504
  request = CLIENT.execute(
@@ -515,6 +529,7 @@ describe Google::APIClient do
515
529
  it 'should succeed when validating parameters in a correct call' do
516
530
  conn = stub_connection do |stub|
517
531
  stub.get('/adsense/v1.3/reports?dimension=DATE&endDate=2010-01-01&metric=PAGE_VIEWS&startDate=2000-01-01') do |env|
532
+ [200, {}, '{}']
518
533
  end
519
534
  end
520
535
  (lambda do
@@ -553,6 +568,7 @@ describe Google::APIClient do
553
568
  stub.get('/adsense/v1.3/reports?dimension=DATE&dimension=PRODUCT_CODE'+
554
569
  '&endDate=2010-01-01&metric=CLICKS&metric=PAGE_VIEWS&'+
555
570
  'startDate=2000-01-01') do |env|
571
+ [200, {}, '{}']
556
572
  end
557
573
  end
558
574
  (lambda do
@@ -593,6 +609,7 @@ describe Google::APIClient do
593
609
  'startDate=2000-01-01') do |env|
594
610
  env.params['dimension'].should include('DATE', 'PRODUCT_CODE')
595
611
  env.params['metric'].should include('CLICKS', 'PAGE_VIEWS')
612
+ [200, {}, '{}']
596
613
  end
597
614
  end
598
615
  request = CLIENT.execute(
@@ -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