jomz-google-api-client 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGELOG.md +144 -0
  2. data/CONTRIBUTING.md +32 -0
  3. data/Gemfile +41 -0
  4. data/LICENSE +202 -0
  5. data/README.md +192 -0
  6. data/Rakefile +46 -0
  7. data/lib/cacerts.pem +2183 -0
  8. data/lib/compat/multi_json.rb +16 -0
  9. data/lib/google/api_client.rb +672 -0
  10. data/lib/google/api_client/auth/compute_service_account.rb +28 -0
  11. data/lib/google/api_client/auth/file_storage.rb +87 -0
  12. data/lib/google/api_client/auth/installed_app.rb +122 -0
  13. data/lib/google/api_client/auth/jwt_asserter.rb +126 -0
  14. data/lib/google/api_client/auth/key_utils.rb +93 -0
  15. data/lib/google/api_client/auth/pkcs12.rb +41 -0
  16. data/lib/google/api_client/batch.rb +323 -0
  17. data/lib/google/api_client/client_secrets.rb +176 -0
  18. data/lib/google/api_client/discovery.rb +19 -0
  19. data/lib/google/api_client/discovery/api.rb +300 -0
  20. data/lib/google/api_client/discovery/media.rb +77 -0
  21. data/lib/google/api_client/discovery/method.rb +363 -0
  22. data/lib/google/api_client/discovery/resource.rb +156 -0
  23. data/lib/google/api_client/discovery/schema.rb +121 -0
  24. data/lib/google/api_client/environment.rb +42 -0
  25. data/lib/google/api_client/errors.rb +60 -0
  26. data/lib/google/api_client/gzip.rb +28 -0
  27. data/lib/google/api_client/logging.rb +32 -0
  28. data/lib/google/api_client/media.rb +259 -0
  29. data/lib/google/api_client/railtie.rb +16 -0
  30. data/lib/google/api_client/reference.rb +27 -0
  31. data/lib/google/api_client/request.rb +351 -0
  32. data/lib/google/api_client/result.rb +253 -0
  33. data/lib/google/api_client/service.rb +233 -0
  34. data/lib/google/api_client/service/batch.rb +103 -0
  35. data/lib/google/api_client/service/request.rb +144 -0
  36. data/lib/google/api_client/service/resource.rb +40 -0
  37. data/lib/google/api_client/service/result.rb +162 -0
  38. data/lib/google/api_client/service/simple_file_store.rb +151 -0
  39. data/lib/google/api_client/service/stub_generator.rb +59 -0
  40. data/lib/google/api_client/service_account.rb +18 -0
  41. data/lib/google/api_client/version.rb +31 -0
  42. data/lib/google/inflection.rb +28 -0
  43. data/spec/fixtures/files/privatekey.p12 +0 -0
  44. data/spec/fixtures/files/sample.txt +33 -0
  45. data/spec/fixtures/files/secret.pem +19 -0
  46. data/spec/google/api_client/batch_spec.rb +249 -0
  47. data/spec/google/api_client/discovery_spec.rb +652 -0
  48. data/spec/google/api_client/gzip_spec.rb +86 -0
  49. data/spec/google/api_client/media_spec.rb +179 -0
  50. data/spec/google/api_client/request_spec.rb +30 -0
  51. data/spec/google/api_client/result_spec.rb +203 -0
  52. data/spec/google/api_client/service_account_spec.rb +164 -0
  53. data/spec/google/api_client/service_spec.rb +586 -0
  54. data/spec/google/api_client/simple_file_store_spec.rb +137 -0
  55. data/spec/google/api_client_spec.rb +253 -0
  56. data/spec/spec_helper.rb +56 -0
  57. data/tasks/gem.rake +97 -0
  58. data/tasks/git.rake +45 -0
  59. data/tasks/metrics.rake +22 -0
  60. data/tasks/spec.rake +57 -0
  61. data/tasks/wiki.rake +82 -0
  62. data/tasks/yard.rake +29 -0
  63. metadata +309 -0
@@ -0,0 +1,28 @@
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
+
16
+ module Google
17
+ if defined?(ActiveSupport::Inflector)
18
+ INFLECTOR = ActiveSupport::Inflector
19
+ else
20
+ begin
21
+ require 'extlib/inflection'
22
+ INFLECTOR = Extlib::Inflection
23
+ rescue LoadError
24
+ require 'active_support/inflector'
25
+ INFLECTOR = ActiveSupport::Inflector
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus posuere urna bibendum diam vulputate fringilla. Fusce elementum fermentum justo id aliquam. Integer vel felis ut arcu elementum lacinia. Duis congue urna eget nisl dapibus tristique molestie turpis sollicitudin. Vivamus in justo quam. Proin condimentum mollis tortor at molestie. Cras luctus, nunc a convallis iaculis, est risus consequat nisi, sit amet sollicitudin metus mi a urna. Aliquam accumsan, massa quis condimentum varius, sapien massa faucibus nibh, a dignissim magna nibh a lacus. Nunc aliquet, nunc ac pulvinar consectetur, sapien lacus hendrerit enim, nec dapibus lorem mi eget risus. Praesent vitae justo eget dolor blandit ullamcorper. Duis id nibh vitae sem aliquam vehicula et ac massa. In neque elit, molestie pulvinar viverra at, vestibulum quis velit.
2
+
3
+ Mauris sit amet placerat enim. Duis vel tellus ac dui auctor tincidunt id nec augue. Donec ut blandit turpis. Mauris dictum urna id urna vestibulum accumsan. Maecenas sagittis urna vitae erat facilisis gravida. Phasellus tellus augue, commodo ut iaculis vitae, interdum ut dolor. Proin at dictum lorem. Quisque pellentesque neque ante, vitae rutrum elit. Pellentesque sit amet erat orci. Praesent justo diam, tristique eu tempus ut, vestibulum eget dui. Maecenas et elementum justo. Cras a augue a elit porttitor placerat eget ut magna.
4
+
5
+ Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam adipiscing tellus in arcu bibendum volutpat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed laoreet faucibus tristique. Duis metus eros, molestie eget dignissim in, imperdiet fermentum nulla. Vestibulum laoreet lorem eu justo vestibulum lobortis. Praesent pharetra leo vel mauris rhoncus commodo sollicitudin ante auctor. Ut sagittis, tortor nec placerat rutrum, neque ipsum cursus nisl, ut lacinia magna risus ac risus. Sed volutpat commodo orci, sodales fermentum dui accumsan eu. Donec egestas ullamcorper elit at condimentum. In euismod sodales posuere. Nullam lacinia tempus molestie. Etiam vitae ullamcorper dui. Fusce congue suscipit arcu, at consectetur diam gravida id. Quisque augue urna, commodo eleifend volutpat vitae, tincidunt ac ligula. Curabitur eget orci nisl, vel placerat ipsum.
6
+
7
+ Curabitur rutrum euismod nisi, consectetur varius tortor condimentum non. Pellentesque rhoncus nisi eu purus ultricies suscipit. Morbi ante nisi, varius nec molestie bibendum, pharetra quis enim. Proin eget nunc ante. Cras aliquam enim vel nunc laoreet ut facilisis nunc interdum. Fusce libero ipsum, posuere eget blandit quis, bibendum vitae quam. Integer dictum faucibus lacus eget facilisis. Duis adipiscing tortor magna, vel tincidunt risus. In non augue eu nisl sodales cursus vel eget nisi. Maecenas dignissim lectus elementum eros fermentum gravida et eget leo. Aenean quis cursus arcu. Mauris posuere purus non diam mattis vehicula. Integer nec orci velit.
8
+
9
+ Integer ac justo ac magna adipiscing condimentum vitae tincidunt dui. Morbi augue arcu, blandit nec interdum sit amet, condimentum vel nisl. Nulla vehicula tincidunt laoreet. Aliquam ornare elementum urna, sed vehicula magna porta id. Vestibulum dictum ultrices tortor sit amet tincidunt. Praesent bibendum, metus vel volutpat interdum, nisl nunc cursus libero, vel congue ligula mi et felis. Nulla mollis elementum nulla, in accumsan risus consequat at. Suspendisse potenti. Vestibulum enim lorem, dignissim ut porta vestibulum, porta eget mi. Fusce a elit ac dui sodales gravida. Pellentesque sed elit at dui dapibus mattis a non arcu.
10
+
11
+ Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In nec posuere augue. Praesent non suscipit arcu. Sed nibh risus, lacinia ut molestie vitae, tristique eget turpis. Sed pretium volutpat arcu, non rutrum leo volutpat sed. Maecenas quis neque nisl, sit amet ornare dolor. Nulla pharetra pulvinar tellus sed eleifend. Aliquam eget mattis nulla. Nulla dictum vehicula velit, non facilisis lorem volutpat id. Fusce scelerisque sem vitae purus dapibus lobortis. Mauris ac turpis nec nibh consequat porttitor. Ut sit amet iaculis lorem. Vivamus blandit erat ac odio venenatis fringilla a sit amet ante. Quisque ut urna sed augue laoreet sagittis.
12
+
13
+ Integer nisl urna, bibendum id lobortis in, tempor non velit. Fusce sed volutpat quam. Suspendisse eu placerat purus. Maecenas quis feugiat lectus. Sed accumsan malesuada dui, a pretium purus facilisis quis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc ac purus id lacus malesuada placerat et in nunc. Ut imperdiet tincidunt est, at consectetur augue egestas hendrerit. Pellentesque eu erat a dui dignissim adipiscing. Integer quis leo non felis placerat eleifend. Fusce luctus mi a lorem mattis eget accumsan libero posuere. Sed pellentesque, odio id pharetra tempus, enim quam placerat metus, auctor aliquam elit mi facilisis quam. Nam at velit et eros rhoncus accumsan.
14
+
15
+ Donec tellus diam, fringilla ac viverra fringilla, rhoncus sit amet purus. Cras et ligula sed nibh tempor gravida. Aliquam id tempus mauris. Ut convallis quam sed arcu varius eget mattis magna tincidunt. Aliquam et suscipit est. Sed metus augue, tristique sed accumsan eget, euismod et augue. Nam augue sapien, placerat vel facilisis eu, tempor id risus. Aliquam mollis egestas mi. Fusce scelerisque convallis mauris quis blandit. Mauris nec ante id lacus sagittis tincidunt ornare vehicula dui. Curabitur tristique mattis nunc, vel cursus libero viverra feugiat. Suspendisse at sapien velit, a lacinia dolor. Vivamus in est non odio feugiat lacinia sodales ut magna.
16
+
17
+ Donec interdum ligula id ipsum dapibus consectetur. Pellentesque vitae posuere ligula. Morbi rhoncus bibendum eleifend. Suspendisse fringilla nunc at elit malesuada vitae ullamcorper lorem laoreet. Suspendisse a ante at ipsum iaculis cursus. Duis accumsan ligula quis nibh luctus pretium. Duis ultrices scelerisque dolor, et vulputate lectus commodo ut.
18
+
19
+ Vestibulum ac tincidunt lorem. Vestibulum lorem massa, dictum a scelerisque ut, convallis vitae eros. Morbi ipsum nisl, lacinia non tempor nec, lobortis id diam. Fusce quis magna nunc. Proin ultricies congue justo sed mattis. Vestibulum sit amet arcu tellus. Quisque ultricies porta massa iaculis vehicula. Vestibulum sollicitudin tempor urna vel sodales. Pellentesque ultricies tellus vel metus porta nec iaculis sapien mollis. Maecenas ullamcorper, metus eget imperdiet sagittis, odio orci dapibus neque, in vulputate nunc nibh non libero. Donec velit quam, lobortis quis tempus a, hendrerit id arcu.
20
+
21
+ Donec nec ante at tortor dignissim mattis. Curabitur vehicula tincidunt magna id sagittis. Proin euismod dignissim porta. Curabitur non turpis purus, in rutrum nulla. Nam turpis nulla, tincidunt et hendrerit non, posuere nec enim. Curabitur leo enim, lobortis ut placerat id, condimentum nec massa. In bibendum, lectus sit amet molestie commodo, felis massa rutrum nisl, ac fermentum ligula lacus in ipsum.
22
+
23
+ Pellentesque mi nulla, scelerisque vitae tempus id, consequat a augue. Quisque vel nisi sit amet ipsum faucibus laoreet sed vitae lorem. Praesent nunc tortor, volutpat ac commodo non, pharetra sed neque. Curabitur nec felis at mi blandit aliquet eu ornare justo. Mauris dignissim purus quis nisl porttitor interdum. Aenean id ipsum enim, blandit commodo justo. Quisque facilisis elit quis velit commodo scelerisque lobortis sapien condimentum. Cras sit amet porttitor velit. Praesent nec tempor arcu.
24
+
25
+ Donec varius mi adipiscing elit semper vel feugiat ipsum dictum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non quam nisl, ac mattis justo. Vestibulum sed massa eget velit tristique auctor ut ac sapien. Curabitur aliquet ligula eget dui ornare at scelerisque mauris faucibus. Vestibulum id mauris metus, sed vestibulum nibh. Nulla egestas dictum blandit. Mauris vitae nibh at dui mollis lobortis. Phasellus sem leo, euismod at fringilla quis, mollis in nibh. Aenean vel lacus et elit pharetra elementum. Aliquam at ligula id sem bibendum volutpat. Pellentesque quis elit a massa dapibus viverra ut et lorem. Donec nulla eros, iaculis nec commodo vel, suscipit sit amet tortor. Integer tempor, elit at viverra imperdiet, velit sapien laoreet nunc, id laoreet ligula risus vel risus. Nullam sed tortor metus.
26
+
27
+ In nunc orci, tempor vulputate pretium vel, suscipit quis risus. Suspendisse accumsan facilisis felis eget posuere. Donec a faucibus felis. Proin nibh erat, sollicitudin quis vestibulum id, tincidunt quis justo. In sed purus eu nisi dignissim condimentum. Sed mattis dapibus lorem id vulputate. Suspendisse nec elit a augue interdum consequat quis id magna. In eleifend aliquam tempor. In in lacus augue.
28
+
29
+ Ut euismod sollicitudin lorem, id aliquam magna dictum sed. Nunc fringilla lobortis nisi sed consectetur. Nulla facilisi. Aenean nec lobortis augue. Curabitur ullamcorper dapibus libero, vel pellentesque arcu sollicitudin non. Praesent varius, turpis nec sollicitudin bibendum, elit tortor rhoncus lacus, gravida luctus leo nisi in felis. Ut metus eros, molestie non faucibus vel, condimentum ac elit.
30
+
31
+ Suspendisse nisl justo, lacinia sit amet interdum nec, tincidunt placerat urna. Suspendisse potenti. In et odio sed purus malesuada cursus sed nec lectus. Cras commodo, orci sit amet hendrerit iaculis, nunc urna facilisis tellus, vel laoreet odio nulla quis nibh. Maecenas ut justo ut lacus posuere sodales. Vestibulum facilisis fringilla diam at volutpat. Proin a hendrerit urna. Aenean placerat pulvinar arcu, sit amet lobortis neque eleifend in. Aenean risus nulla, facilisis ut tincidunt vitae, fringilla at ligula. Praesent eleifend est at sem lacinia auctor. Nulla ornare nunc in erat laoreet blandit.
32
+
33
+ Suspendisse pharetra leo ac est porta consequat. Nunc sem nibh, gravida vel aliquam a, ornare in tortor. Nulla vel sapien et felis placerat pellentesque id scelerisque nisl. Praesent et posuere.
@@ -0,0 +1,19 @@
1
+ Bag Attributes
2
+ friendlyName: privatekey
3
+ localKeyID: 54 69 6D 65 20 31 33 35 31 38 38 38 31 37 38 36 39 36
4
+ Key Attributes: <No Attributes>
5
+ -----BEGIN RSA PRIVATE KEY-----
6
+ MIICXAIBAAKBgQDYDyPb3GhyFx5i/wxS/jFsO6wSLys1ehAk6QZoBXGlg7ETVrIJ
7
+ HYh9gXQUno4tJiQoaO8wOvleIRrqI0LkiftCXKWVSrzOiV+O9GkKx1byw1yAIZus
8
+ QdwMT7X0O9hrZLZwhICWC9s6cGhnlCVxLIP/+JkVK7hxEq/LxoSszNV77wIDAQAB
9
+ AoGAa2G69L7quil7VMBmI6lqbtyJfNAsrXtpIq8eG/z4qsZ076ObAKTI/XeldcoH
10
+ 57CZL+xXVKU64umZMt0rleJuGXdlauEUbsSx+biGewRfGTgC4rUSjmE539rBvmRW
11
+ gaKliorepPMp/+B9CcG/2YfDPRvG/2cgTXJHVvneo+xHL4ECQQD2Jx5Mvs8z7s2E
12
+ jY1mkpRKqh4Z7rlitkAwe1NXcVC8hz5ASu7ORyTl8EPpKAfRMYl1ofK/ozT1URXf
13
+ kL5nChPfAkEA4LPUJ6cqrY4xrrtdGaM4iGIxzen5aZlKz/YNlq5LuQKbnLLHMuXU
14
+ ohp/ynpqNWbcAFbmtGSMayxGKW5+fJgZ8QJAUBOZv82zCmn9YcnK3juBEmkVMcp/
15
+ dKVlbGAyVJgAc9RrY+78kQ6D6mmnLgpfwKYk2ae9mKo3aDbgrsIfrtWQcQJAfFGi
16
+ CEpJp3orbLQG319ZsMM7MOTJdC42oPZOMFbAWFzkAX88DKHx0bn9h+XQizkccSej
17
+ Ppz+v3DgZJ3YZ1Cz0QJBALiqIokZ+oa3AY6oT0aiec6txrGvNPPbwOsrBpFqGNbu
18
+ AByzWWBoBi40eKMSIR30LqN9H8YnJ91Aoy1njGYyQaw=
19
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,249 @@
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
+ require 'google/api_client'
17
+ require 'google/api_client/version'
18
+
19
+ describe Google::APIClient::BatchRequest do
20
+ CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
21
+
22
+ after do
23
+ # Reset client to not-quite-pristine state
24
+ CLIENT.key = nil
25
+ CLIENT.user_ip = nil
26
+ end
27
+
28
+ it 'should raise an error if making an empty batch request' do
29
+ batch = Google::APIClient::BatchRequest.new
30
+
31
+ (lambda do
32
+ CLIENT.execute(batch)
33
+ end).should raise_error(Google::APIClient::BatchError)
34
+ end
35
+
36
+ it 'should allow query parameters in batch requests' do
37
+ batch = Google::APIClient::BatchRequest.new
38
+ batch.add(:uri => 'https://example.com', :parameters => {
39
+ 'a' => '12345'
40
+ })
41
+ method, uri, headers, body = batch.to_http_request
42
+ body.read.should include("/?a=12345")
43
+ end
44
+
45
+ describe 'with the discovery API' do
46
+ before do
47
+ CLIENT.authorization = nil
48
+ @discovery = CLIENT.discovered_api('discovery', 'v1')
49
+ end
50
+
51
+ describe 'with two valid requests' do
52
+ before do
53
+ @call1 = {
54
+ :api_method => @discovery.apis.get_rest,
55
+ :parameters => {
56
+ 'api' => 'plus',
57
+ 'version' => 'v1'
58
+ }
59
+ }
60
+
61
+ @call2 = {
62
+ :api_method => @discovery.apis.get_rest,
63
+ :parameters => {
64
+ 'api' => 'discovery',
65
+ 'version' => 'v1'
66
+ }
67
+ }
68
+ end
69
+
70
+ it 'should execute both when using a global callback' do
71
+ block_called = 0
72
+ ids = ['first_call', 'second_call']
73
+ expected_ids = ids.clone
74
+ batch = Google::APIClient::BatchRequest.new do |result|
75
+ block_called += 1
76
+ result.status.should == 200
77
+ expected_ids.should include(result.response.call_id)
78
+ expected_ids.delete(result.response.call_id)
79
+ end
80
+
81
+ batch.add(@call1, ids[0])
82
+ batch.add(@call2, ids[1])
83
+
84
+ CLIENT.execute(batch)
85
+ block_called.should == 2
86
+ end
87
+
88
+ it 'should execute both when using individual callbacks' do
89
+ batch = Google::APIClient::BatchRequest.new
90
+
91
+ call1_returned, call2_returned = false, false
92
+ batch.add(@call1) do |result|
93
+ call1_returned = true
94
+ result.status.should == 200
95
+ end
96
+ batch.add(@call2) do |result|
97
+ call2_returned = true
98
+ result.status.should == 200
99
+ end
100
+
101
+ CLIENT.execute(batch)
102
+ call1_returned.should == true
103
+ call2_returned.should == true
104
+ end
105
+
106
+ it 'should raise an error if using the same call ID more than once' do
107
+ batch = Google::APIClient::BatchRequest.new
108
+
109
+ (lambda do
110
+ batch.add(@call1, 'my_id')
111
+ batch.add(@call2, 'my_id')
112
+ end).should raise_error(Google::APIClient::BatchError)
113
+ end
114
+ end
115
+
116
+ describe 'with a valid request and an invalid one' do
117
+ before do
118
+ @call1 = {
119
+ :api_method => @discovery.apis.get_rest,
120
+ :parameters => {
121
+ 'api' => 'plus',
122
+ 'version' => 'v1'
123
+ }
124
+ }
125
+
126
+ @call2 = {
127
+ :api_method => @discovery.apis.get_rest,
128
+ :parameters => {
129
+ 'api' => 0,
130
+ 'version' => 1
131
+ }
132
+ }
133
+ end
134
+
135
+ it 'should execute both when using a global callback' do
136
+ block_called = 0
137
+ ids = ['first_call', 'second_call']
138
+ expected_ids = ids.clone
139
+ batch = Google::APIClient::BatchRequest.new do |result|
140
+ block_called += 1
141
+ expected_ids.should include(result.response.call_id)
142
+ expected_ids.delete(result.response.call_id)
143
+ if result.response.call_id == ids[0]
144
+ result.status.should == 200
145
+ else
146
+ result.status.should >= 400
147
+ result.status.should < 500
148
+ end
149
+ end
150
+
151
+ batch.add(@call1, ids[0])
152
+ batch.add(@call2, ids[1])
153
+
154
+ CLIENT.execute(batch)
155
+ block_called.should == 2
156
+ end
157
+
158
+ it 'should execute both when using individual callbacks' do
159
+ batch = Google::APIClient::BatchRequest.new
160
+
161
+ call1_returned, call2_returned = false, false
162
+ batch.add(@call1) do |result|
163
+ call1_returned = true
164
+ result.status.should == 200
165
+ end
166
+ batch.add(@call2) do |result|
167
+ call2_returned = true
168
+ result.status.should >= 400
169
+ result.status.should < 500
170
+ end
171
+
172
+ CLIENT.execute(batch)
173
+ call1_returned.should == true
174
+ call2_returned.should == true
175
+ end
176
+ end
177
+ end
178
+
179
+ describe 'with the calendar API' do
180
+ before do
181
+ CLIENT.authorization = nil
182
+ @calendar = CLIENT.discovered_api('calendar', 'v3')
183
+ end
184
+
185
+ describe 'with two valid requests' do
186
+ before do
187
+ event1 = {
188
+ 'summary' => 'Appointment 1',
189
+ 'location' => 'Somewhere',
190
+ 'start' => {
191
+ 'dateTime' => '2011-01-01T10:00:00.000-07:00'
192
+ },
193
+ 'end' => {
194
+ 'dateTime' => '2011-01-01T10:25:00.000-07:00'
195
+ },
196
+ 'attendees' => [
197
+ {
198
+ 'email' => 'myemail@mydomain.tld'
199
+ }
200
+ ]
201
+ }
202
+
203
+ event2 = {
204
+ 'summary' => 'Appointment 2',
205
+ 'location' => 'Somewhere as well',
206
+ 'start' => {
207
+ 'dateTime' => '2011-01-02T10:00:00.000-07:00'
208
+ },
209
+ 'end' => {
210
+ 'dateTime' => '2011-01-02T10:25:00.000-07:00'
211
+ },
212
+ 'attendees' => [
213
+ {
214
+ 'email' => 'myemail@mydomain.tld'
215
+ }
216
+ ]
217
+ }
218
+
219
+ @call1 = {
220
+ :api_method => @calendar.events.insert,
221
+ :parameters => {'calendarId' => 'myemail@mydomain.tld'},
222
+ :body => MultiJson.dump(event1),
223
+ :headers => {'Content-Type' => 'application/json'}
224
+ }
225
+
226
+ @call2 = {
227
+ :api_method => @calendar.events.insert,
228
+ :parameters => {'calendarId' => 'myemail@mydomain.tld'},
229
+ :body => MultiJson.dump(event2),
230
+ :headers => {'Content-Type' => 'application/json'}
231
+ }
232
+ end
233
+
234
+ it 'should convert to a correct HTTP request' do
235
+ batch = Google::APIClient::BatchRequest.new { |result| }
236
+ batch.add(@call1, '1').add(@call2, '2')
237
+ request = batch.to_env(CLIENT.connection)
238
+ boundary = Google::APIClient::BatchRequest::BATCH_BOUNDARY
239
+ request[:method].to_s.downcase.should == 'post'
240
+ request[:url].to_s.should == 'https://www.googleapis.com/batch'
241
+ request[:request_headers]['Content-Type'].should == "multipart/mixed;boundary=#{boundary}"
242
+ # TODO - Fix headers
243
+ #expected_body = /--#{Regexp.escape(boundary)}\nContent-Type: +application\/http\nContent-ID: +<[\w-]+\+1>\n\nPOST +https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/myemail@mydomain.tld\/events +HTTP\/1.1\nContent-Type: +application\/json\n\n#{Regexp.escape(@call1[:body])}\n\n--#{boundary}\nContent-Type: +application\/http\nContent-ID: +<[\w-]+\+2>\n\nPOST +https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/myemail@mydomain.tld\/events HTTP\/1.1\nContent-Type: +application\/json\n\n#{Regexp.escape(@call2[:body])}\n\n--#{Regexp.escape(boundary)}--/
244
+ #request[:body].read.gsub("\r", "").should =~ expected_body
245
+ end
246
+ end
247
+
248
+ end
249
+ end
@@ -0,0 +1,652 @@
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 'multi_json'
22
+ require 'compat/multi_json'
23
+ require 'signet/oauth_1/client'
24
+ require 'google/api_client'
25
+ require 'google/api_client/version'
26
+
27
+ describe Google::APIClient do
28
+ include ConnectionHelpers
29
+ CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
30
+
31
+ after do
32
+ # Reset client to not-quite-pristine state
33
+ CLIENT.key = nil
34
+ CLIENT.user_ip = nil
35
+ end
36
+
37
+ it 'should raise a type error for bogus authorization' do
38
+ (lambda do
39
+ Google::APIClient.new(:application_name => 'API Client Tests', :authorization => 42)
40
+ end).should raise_error(TypeError)
41
+ end
42
+
43
+ it 'should not be able to retrieve the discovery document for a bogus API' do
44
+ (lambda do
45
+ CLIENT.discovery_document('bogus')
46
+ end).should raise_error(Google::APIClient::TransmissionError)
47
+ (lambda do
48
+ CLIENT.discovered_api('bogus')
49
+ end).should raise_error(Google::APIClient::TransmissionError)
50
+ end
51
+
52
+ it 'should raise an error for bogus services' do
53
+ (lambda do
54
+ CLIENT.discovered_api(42)
55
+ end).should raise_error(TypeError)
56
+ end
57
+
58
+ it 'should raise an error for bogus services' do
59
+ (lambda do
60
+ CLIENT.preferred_version(42)
61
+ end).should raise_error(TypeError)
62
+ end
63
+
64
+ it 'should raise an error for bogus methods' do
65
+ (lambda do
66
+ CLIENT.execute(42)
67
+ end).should raise_error(TypeError)
68
+ end
69
+
70
+ it 'should not return a preferred version for bogus service names' do
71
+ CLIENT.preferred_version('bogus').should == nil
72
+ end
73
+
74
+ describe 'with the prediction API' do
75
+ before do
76
+ CLIENT.authorization = nil
77
+ # The prediction API no longer exposes a v1, so we have to be
78
+ # careful about looking up the wrong API version.
79
+ @prediction = CLIENT.discovered_api('prediction', 'v1.2')
80
+ end
81
+
82
+ it 'should correctly determine the discovery URI' do
83
+ CLIENT.discovery_uri('prediction').should ===
84
+ 'https://www.googleapis.com/discovery/v1/apis/prediction/v1/rest'
85
+ end
86
+
87
+ it 'should correctly determine the discovery URI if :user_ip is set' do
88
+ CLIENT.user_ip = '127.0.0.1'
89
+
90
+ conn = stub_connection do |stub|
91
+ stub.get('/discovery/v1/apis/prediction/v1.2/rest?userIp=127.0.0.1') do |env|
92
+ [200, {}, '{}']
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
+ [200, {}, '{}']
109
+ end
110
+ end
111
+ request = CLIENT.execute(
112
+ :http_method => 'GET',
113
+ :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
114
+ :authenticated => false,
115
+ :connection => conn
116
+ )
117
+ conn.verify
118
+ end
119
+
120
+ it 'should correctly determine the discovery URI if both are set' do
121
+ CLIENT.key = 'qwerty'
122
+ CLIENT.user_ip = '127.0.0.1'
123
+ conn = stub_connection do |stub|
124
+ stub.get('/discovery/v1/apis/prediction/v1.2/rest?key=qwerty&userIp=127.0.0.1') do |env|
125
+ [200, {}, '{}']
126
+ end
127
+ end
128
+ request = CLIENT.execute(
129
+ :http_method => 'GET',
130
+ :uri => CLIENT.discovery_uri('prediction', 'v1.2'),
131
+ :authenticated => false,
132
+ :connection => conn
133
+ )
134
+ conn.verify
135
+ end
136
+
137
+ it 'should correctly generate API objects' do
138
+ CLIENT.discovered_api('prediction', 'v1.2').name.should == 'prediction'
139
+ CLIENT.discovered_api('prediction', 'v1.2').version.should == 'v1.2'
140
+ CLIENT.discovered_api(:prediction, 'v1.2').name.should == 'prediction'
141
+ CLIENT.discovered_api(:prediction, 'v1.2').version.should == 'v1.2'
142
+ end
143
+
144
+ it 'should discover methods' do
145
+ CLIENT.discovered_method(
146
+ 'prediction.training.insert', 'prediction', 'v1.2'
147
+ ).name.should == 'insert'
148
+ CLIENT.discovered_method(
149
+ :'prediction.training.insert', :prediction, 'v1.2'
150
+ ).name.should == 'insert'
151
+ CLIENT.discovered_method(
152
+ 'prediction.training.delete', 'prediction', 'v1.2'
153
+ ).name.should == 'delete'
154
+ end
155
+
156
+ it 'should define the origin API in discovered methods' do
157
+ CLIENT.discovered_method(
158
+ 'prediction.training.insert', 'prediction', 'v1.2'
159
+ ).api.name.should == 'prediction'
160
+ end
161
+
162
+ it 'should not find methods that are not in the discovery document' do
163
+ CLIENT.discovered_method(
164
+ 'prediction.bogus', 'prediction', 'v1.2'
165
+ ).should == nil
166
+ end
167
+
168
+ it 'should raise an error for bogus methods' do
169
+ (lambda do
170
+ CLIENT.discovered_method(42, 'prediction', 'v1.2')
171
+ end).should raise_error(TypeError)
172
+ end
173
+
174
+ it 'should raise an error for bogus methods' do
175
+ (lambda do
176
+ CLIENT.execute(:api_method => CLIENT.discovered_api('prediction', 'v1.2'))
177
+ end).should raise_error(TypeError)
178
+ end
179
+
180
+ it 'should correctly determine the preferred version' do
181
+ CLIENT.preferred_version('prediction').version.should_not == 'v1'
182
+ CLIENT.preferred_version(:prediction).version.should_not == 'v1'
183
+ end
184
+
185
+ it 'should return a batch path' do
186
+ CLIENT.discovered_api('prediction', 'v1.2').batch_path.should_not be_nil
187
+ end
188
+
189
+ it 'should generate valid requests' do
190
+ conn = stub_connection do |stub|
191
+ stub.post('/prediction/v1.2/training?data=12345') do |env|
192
+ env[:body].should == ''
193
+ [200, {}, '{}']
194
+ end
195
+ end
196
+ request = CLIENT.execute(
197
+ :api_method => @prediction.training.insert,
198
+ :parameters => {'data' => '12345'},
199
+ :connection => conn
200
+ )
201
+ conn.verify
202
+ end
203
+
204
+ it 'should generate valid requests when parameter value includes semicolon' do
205
+ conn = stub_connection do |stub|
206
+ # semicolon (;) in parameter value was being converted to
207
+ # bare ampersand (&) in 0.4.7. ensure that it gets converted
208
+ # to a CGI-escaped semicolon (%3B) instead.
209
+ stub.post('/prediction/v1.2/training?data=12345%3B67890') do |env|
210
+ env[:body].should == ''
211
+ [200, {}, '{}']
212
+ end
213
+ end
214
+ request = CLIENT.execute(
215
+ :api_method => @prediction.training.insert,
216
+ :parameters => {'data' => '12345;67890'},
217
+ :connection => conn
218
+ )
219
+ conn.verify
220
+ end
221
+
222
+ it 'should generate valid requests when multivalued parameters are passed' do
223
+ conn = stub_connection do |stub|
224
+ stub.post('/prediction/v1.2/training?data=1&data=2') do |env|
225
+ env.params['data'].should include('1', '2')
226
+ [200, {}, '{}']
227
+ end
228
+ end
229
+ request = CLIENT.execute(
230
+ :api_method => @prediction.training.insert,
231
+ :parameters => {'data' => ['1', '2']},
232
+ :connection => conn
233
+ )
234
+ conn.verify
235
+ end
236
+
237
+ it 'should generate requests against the correct URIs' do
238
+ conn = stub_connection do |stub|
239
+ stub.post('/prediction/v1.2/training?data=12345') do |env|
240
+ [200, {}, '{}']
241
+ end
242
+ end
243
+ request = CLIENT.execute(
244
+ :api_method => @prediction.training.insert,
245
+ :parameters => {'data' => '12345'},
246
+ :connection => conn
247
+ )
248
+ conn.verify
249
+ end
250
+
251
+ it 'should generate requests against the correct URIs' do
252
+ conn = stub_connection do |stub|
253
+ stub.post('/prediction/v1.2/training?data=12345') do |env|
254
+ [200, {}, '{}']
255
+ end
256
+ end
257
+ request = CLIENT.execute(
258
+ :api_method => @prediction.training.insert,
259
+ :parameters => {'data' => '12345'},
260
+ :connection => conn
261
+ )
262
+ conn.verify
263
+ end
264
+
265
+ it 'should allow modification to the base URIs for testing purposes' do
266
+ # Using a new client instance here to avoid caching rebased discovery doc
267
+ prediction_rebase =
268
+ Google::APIClient.new(:application_name => 'API Client Tests').discovered_api('prediction', 'v1.2')
269
+ prediction_rebase.method_base =
270
+ 'https://testing-domain.example.com/prediction/v1.2/'
271
+
272
+ conn = stub_connection do |stub|
273
+ stub.post('/prediction/v1.2/training') do |env|
274
+ env[:url].host.should == 'testing-domain.example.com'
275
+ [200, {}, '{}']
276
+ end
277
+ end
278
+
279
+ request = CLIENT.execute(
280
+ :api_method => prediction_rebase.training.insert,
281
+ :parameters => {'data' => '123'},
282
+ :connection => conn
283
+ )
284
+ conn.verify
285
+ end
286
+
287
+ it 'should generate OAuth 1 requests' do
288
+ CLIENT.authorization = :oauth_1
289
+ CLIENT.authorization.token_credential_key = '12345'
290
+ CLIENT.authorization.token_credential_secret = '12345'
291
+
292
+ conn = stub_connection do |stub|
293
+ stub.post('/prediction/v1.2/training?data=12345') do |env|
294
+ env[:request_headers].should have_key('Authorization')
295
+ env[:request_headers]['Authorization'].should =~ /^OAuth/
296
+ [200, {}, '{}']
297
+ end
298
+ end
299
+
300
+ request = CLIENT.execute(
301
+ :api_method => @prediction.training.insert,
302
+ :parameters => {'data' => '12345'},
303
+ :connection => conn
304
+ )
305
+ conn.verify
306
+ end
307
+
308
+ it 'should generate OAuth 2 requests' do
309
+ CLIENT.authorization = :oauth_2
310
+ CLIENT.authorization.access_token = '12345'
311
+
312
+ conn = stub_connection do |stub|
313
+ stub.post('/prediction/v1.2/training?data=12345') do |env|
314
+ env[:request_headers].should have_key('Authorization')
315
+ env[:request_headers]['Authorization'].should =~ /^Bearer/
316
+ [200, {}, '{}']
317
+ end
318
+ end
319
+
320
+ request = CLIENT.execute(
321
+ :api_method => @prediction.training.insert,
322
+ :parameters => {'data' => '12345'},
323
+ :connection => conn
324
+ )
325
+ conn.verify
326
+ end
327
+
328
+ it 'should not be able to execute improperly authorized requests' do
329
+ CLIENT.authorization = :oauth_1
330
+ CLIENT.authorization.token_credential_key = '12345'
331
+ CLIENT.authorization.token_credential_secret = '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
+ CLIENT.authorization = :oauth_2
341
+ CLIENT.authorization.access_token = '12345'
342
+ result = CLIENT.execute(
343
+ @prediction.training.insert,
344
+ {'data' => '12345'}
345
+ )
346
+ result.response.status.should == 401
347
+ end
348
+
349
+ it 'should not be able to execute improperly authorized requests' do
350
+ (lambda do
351
+ CLIENT.authorization = :oauth_1
352
+ CLIENT.authorization.token_credential_key = '12345'
353
+ CLIENT.authorization.token_credential_secret = '12345'
354
+ result = CLIENT.execute!(
355
+ @prediction.training.insert,
356
+ {'data' => '12345'}
357
+ )
358
+ end).should raise_error(Google::APIClient::ClientError)
359
+ end
360
+
361
+ it 'should not be able to execute improperly authorized requests' do
362
+ (lambda do
363
+ CLIENT.authorization = :oauth_2
364
+ CLIENT.authorization.access_token = '12345'
365
+ result = CLIENT.execute!(
366
+ @prediction.training.insert,
367
+ {'data' => '12345'}
368
+ )
369
+ end).should raise_error(Google::APIClient::ClientError)
370
+ end
371
+
372
+ it 'should correctly handle unnamed parameters' do
373
+ conn = stub_connection do |stub|
374
+ stub.post('/prediction/v1.2/training') do |env|
375
+ env[:request_headers].should have_key('Content-Type')
376
+ env[:request_headers]['Content-Type'].should == 'application/json'
377
+ [200, {}, '{}']
378
+ end
379
+ end
380
+ CLIENT.authorization = :oauth_2
381
+ CLIENT.authorization.access_token = '12345'
382
+ CLIENT.execute(
383
+ :api_method => @prediction.training.insert,
384
+ :body => MultiJson.dump({"id" => "bucket/object"}),
385
+ :headers => {'Content-Type' => 'application/json'},
386
+ :connection => conn
387
+ )
388
+ conn.verify
389
+ end
390
+ end
391
+
392
+ describe 'with the plus API' do
393
+ before do
394
+ CLIENT.authorization = nil
395
+ @plus = CLIENT.discovered_api('plus')
396
+ end
397
+
398
+ it 'should correctly determine the discovery URI' do
399
+ CLIENT.discovery_uri('plus').should ===
400
+ 'https://www.googleapis.com/discovery/v1/apis/plus/v1/rest'
401
+ end
402
+
403
+ it 'should find APIs that are in the discovery document' do
404
+ CLIENT.discovered_api('plus').name.should == 'plus'
405
+ CLIENT.discovered_api('plus').version.should == 'v1'
406
+ CLIENT.discovered_api(:plus).name.should == 'plus'
407
+ CLIENT.discovered_api(:plus).version.should == 'v1'
408
+ end
409
+
410
+ it 'should find methods that are in the discovery document' do
411
+ # TODO(bobaman) Fix this when the RPC names are correct
412
+ CLIENT.discovered_method(
413
+ 'plus.activities.list', 'plus'
414
+ ).name.should == 'list'
415
+ end
416
+
417
+ it 'should define the origin API in discovered methods' do
418
+ CLIENT.discovered_method(
419
+ 'plus.activities.list', 'plus'
420
+ ).api.name.should == 'plus'
421
+ end
422
+
423
+ it 'should not find methods that are not in the discovery document' do
424
+ CLIENT.discovered_method('plus.bogus', 'plus').should == nil
425
+ end
426
+
427
+ it 'should generate requests against the correct URIs' do
428
+ conn = stub_connection do |stub|
429
+ stub.get('/plus/v1/people/107807692475771887386/activities/public') do |env|
430
+ [200, {}, '{}']
431
+ end
432
+ end
433
+
434
+ request = CLIENT.execute(
435
+ :api_method => @plus.activities.list,
436
+ :parameters => {
437
+ 'userId' => '107807692475771887386', 'collection' => 'public'
438
+ },
439
+ :authenticated => false,
440
+ :connection => conn
441
+ )
442
+ conn.verify
443
+ end
444
+
445
+ it 'should correctly validate parameters' do
446
+ (lambda do
447
+ CLIENT.execute(
448
+ :api_method => @plus.activities.list,
449
+ :parameters => {'alt' => 'json'},
450
+ :authenticated => false
451
+ )
452
+ end).should raise_error(ArgumentError)
453
+ end
454
+
455
+ it 'should correctly validate parameters' do
456
+ (lambda do
457
+ CLIENT.execute(
458
+ :api_method => @plus.activities.list,
459
+ :parameters => {
460
+ 'userId' => '107807692475771887386', 'collection' => 'bogus'
461
+ },
462
+ :authenticated => false
463
+ ).to_env(CLIENT.connection)
464
+ end).should raise_error(ArgumentError)
465
+ end
466
+ end
467
+
468
+ describe 'with the adsense API' do
469
+ before do
470
+ CLIENT.authorization = nil
471
+ @adsense = CLIENT.discovered_api('adsense', 'v1.3')
472
+ end
473
+
474
+ it 'should correctly determine the discovery URI' do
475
+ CLIENT.discovery_uri('adsense', 'v1.3').to_s.should ===
476
+ 'https://www.googleapis.com/discovery/v1/apis/adsense/v1.3/rest'
477
+ end
478
+
479
+ it 'should find APIs that are in the discovery document' do
480
+ CLIENT.discovered_api('adsense', 'v1.3').name.should == 'adsense'
481
+ CLIENT.discovered_api('adsense', 'v1.3').version.should == 'v1.3'
482
+ end
483
+
484
+ it 'should return a batch path' do
485
+ CLIENT.discovered_api('adsense', 'v1.3').batch_path.should_not be_nil
486
+ end
487
+
488
+ it 'should find methods that are in the discovery document' do
489
+ CLIENT.discovered_method(
490
+ 'adsense.reports.generate', 'adsense', 'v1.3'
491
+ ).name.should == 'generate'
492
+ end
493
+
494
+ it 'should not find methods that are not in the discovery document' do
495
+ CLIENT.discovered_method('adsense.bogus', 'adsense', 'v1.3').should == nil
496
+ end
497
+
498
+ it 'should generate requests against the correct URIs' do
499
+ conn = stub_connection do |stub|
500
+ stub.get('/adsense/v1.3/adclients') do |env|
501
+ [200, {}, '{}']
502
+ end
503
+ end
504
+ request = CLIENT.execute(
505
+ :api_method => @adsense.adclients.list,
506
+ :authenticated => false,
507
+ :connection => conn
508
+ )
509
+ conn.verify
510
+ end
511
+
512
+ it 'should not be able to execute requests without authorization' do
513
+ result = CLIENT.execute(
514
+ :api_method => @adsense.adclients.list,
515
+ :authenticated => false
516
+ )
517
+ result.response.status.should == 401
518
+ end
519
+
520
+ it 'should fail when validating missing required parameters' do
521
+ (lambda do
522
+ CLIENT.execute(
523
+ :api_method => @adsense.reports.generate,
524
+ :authenticated => false
525
+ )
526
+ end).should raise_error(ArgumentError)
527
+ end
528
+
529
+ it 'should succeed when validating parameters in a correct call' do
530
+ conn = stub_connection do |stub|
531
+ stub.get('/adsense/v1.3/reports?dimension=DATE&endDate=2010-01-01&metric=PAGE_VIEWS&startDate=2000-01-01') do |env|
532
+ [200, {}, '{}']
533
+ end
534
+ end
535
+ (lambda do
536
+ CLIENT.execute(
537
+ :api_method => @adsense.reports.generate,
538
+ :parameters => {
539
+ 'startDate' => '2000-01-01',
540
+ 'endDate' => '2010-01-01',
541
+ 'dimension' => 'DATE',
542
+ 'metric' => 'PAGE_VIEWS'
543
+ },
544
+ :authenticated => false,
545
+ :connection => conn
546
+ )
547
+ end).should_not raise_error
548
+ conn.verify
549
+ end
550
+
551
+ it 'should fail when validating parameters with invalid values' do
552
+ (lambda do
553
+ CLIENT.execute(
554
+ :api_method => @adsense.reports.generate,
555
+ :parameters => {
556
+ 'startDate' => '2000-01-01',
557
+ 'endDate' => '2010-01-01',
558
+ 'dimension' => 'BAD_CHARACTERS=-&*(£&',
559
+ 'metric' => 'PAGE_VIEWS'
560
+ },
561
+ :authenticated => false
562
+ )
563
+ end).should raise_error(ArgumentError)
564
+ end
565
+
566
+ it 'should succeed when validating repeated parameters in a correct call' do
567
+ conn = stub_connection do |stub|
568
+ stub.get('/adsense/v1.3/reports?dimension=DATE&dimension=PRODUCT_CODE'+
569
+ '&endDate=2010-01-01&metric=CLICKS&metric=PAGE_VIEWS&'+
570
+ 'startDate=2000-01-01') do |env|
571
+ [200, {}, '{}']
572
+ end
573
+ end
574
+ (lambda do
575
+ CLIENT.execute(
576
+ :api_method => @adsense.reports.generate,
577
+ :parameters => {
578
+ 'startDate' => '2000-01-01',
579
+ 'endDate' => '2010-01-01',
580
+ 'dimension' => ['DATE', 'PRODUCT_CODE'],
581
+ 'metric' => ['PAGE_VIEWS', 'CLICKS']
582
+ },
583
+ :authenticated => false,
584
+ :connection => conn
585
+ )
586
+ end).should_not raise_error
587
+ conn.verify
588
+ end
589
+
590
+ it 'should fail when validating incorrect repeated parameters' do
591
+ (lambda do
592
+ CLIENT.execute(
593
+ :api_method => @adsense.reports.generate,
594
+ :parameters => {
595
+ 'startDate' => '2000-01-01',
596
+ 'endDate' => '2010-01-01',
597
+ 'dimension' => ['DATE', 'BAD_CHARACTERS=-&*(£&'],
598
+ 'metric' => ['PAGE_VIEWS', 'CLICKS']
599
+ },
600
+ :authenticated => false
601
+ )
602
+ end).should raise_error(ArgumentError)
603
+ end
604
+
605
+ it 'should generate valid requests when multivalued parameters are passed' do
606
+ conn = stub_connection do |stub|
607
+ stub.get('/adsense/v1.3/reports?dimension=DATE&dimension=PRODUCT_CODE'+
608
+ '&endDate=2010-01-01&metric=CLICKS&metric=PAGE_VIEWS&'+
609
+ 'startDate=2000-01-01') do |env|
610
+ env.params['dimension'].should include('DATE', 'PRODUCT_CODE')
611
+ env.params['metric'].should include('CLICKS', 'PAGE_VIEWS')
612
+ [200, {}, '{}']
613
+ end
614
+ end
615
+ request = CLIENT.execute(
616
+ :api_method => @adsense.reports.generate,
617
+ :parameters => {
618
+ 'startDate' => '2000-01-01',
619
+ 'endDate' => '2010-01-01',
620
+ 'dimension' => ['DATE', 'PRODUCT_CODE'],
621
+ 'metric' => ['PAGE_VIEWS', 'CLICKS']
622
+ },
623
+ :authenticated => false,
624
+ :connection => conn
625
+ )
626
+ conn.verify
627
+ end
628
+ end
629
+
630
+ describe 'with the Drive API' do
631
+ before do
632
+ CLIENT.authorization = nil
633
+ @drive = CLIENT.discovered_api('drive', 'v1')
634
+ end
635
+
636
+ it 'should include media upload info methods' do
637
+ @drive.files.insert.media_upload.should_not == nil
638
+ end
639
+
640
+ it 'should include accepted media types' do
641
+ @drive.files.insert.media_upload.accepted_types.should_not be_empty
642
+ end
643
+
644
+ it 'should have an upload path' do
645
+ @drive.files.insert.media_upload.uri_template.should_not == nil
646
+ end
647
+
648
+ it 'should have a max file size' do
649
+ @drive.files.insert.media_upload.max_size.should_not == nil
650
+ end
651
+ end
652
+ end