google-api-client 0.4.7 → 0.5.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.
@@ -71,68 +71,56 @@ describe Google::APIClient::ResumableUpload do
71
71
  @file = File.expand_path('files/sample.txt', fixtures_path)
72
72
  @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
73
73
  @uploader = Google::APIClient::ResumableUpload.new(
74
- mock_result(308),
75
- @media,
76
- 'https://www.googleapis.com/upload/drive/v1/files/12345')
74
+ :media => @media,
75
+ :api_method => @drive.files.insert,
76
+ :uri => 'https://www.googleapis.com/upload/drive/v1/files/12345')
77
77
  end
78
78
 
79
79
  it 'should consider 20x status as complete' do
80
- api_client = stub('api', :execute => mock_result(200))
81
- @uploader.send_chunk(api_client)
80
+ request = @uploader.to_http_request
81
+ @uploader.process_http_response(mock_result(200))
82
82
  @uploader.complete?.should == true
83
83
  end
84
84
 
85
85
  it 'should consider 30x status as incomplete' do
86
- api_client = stub('api', :execute => mock_result(308))
87
- @uploader.send_chunk(api_client)
86
+ request = @uploader.to_http_request
87
+ @uploader.process_http_response(mock_result(308))
88
88
  @uploader.complete?.should == false
89
89
  @uploader.expired?.should == false
90
90
  end
91
91
 
92
92
  it 'should consider 40x status as fatal' do
93
- api_client = stub('api', :execute => mock_result(404))
94
- @uploader.send_chunk(api_client)
93
+ request = @uploader.to_http_request
94
+ @uploader.process_http_response(mock_result(404))
95
95
  @uploader.expired?.should == true
96
96
  end
97
97
 
98
98
  it 'should detect changes to location' do
99
- api_client = stub('api', :execute => mock_result(308, 'location' => 'https://www.googleapis.com/upload/drive/v1/files/abcdef'))
100
- @uploader.send_chunk(api_client)
101
- @uploader.location.should == 'https://www.googleapis.com/upload/drive/v1/files/abcdef'
99
+ request = @uploader.to_http_request
100
+ @uploader.process_http_response(mock_result(308, 'location' => 'https://www.googleapis.com/upload/drive/v1/files/abcdef'))
101
+ @uploader.uri.to_s.should == 'https://www.googleapis.com/upload/drive/v1/files/abcdef'
102
102
  end
103
103
 
104
- it 'should resume from the saved range reported by the server' do
105
- api_client = mock('api')
106
- api_client.should_receive(:execute).and_return(mock_result(308, 'range' => '0-99'))
107
- api_client.should_receive(:execute).with(
108
- hash_including(:headers => hash_including(
109
- "Content-Range" => "bytes 100-299/#{@media.length}",
110
- "Content-Length" => "200"
111
- ))).and_return(mock_result(308))
112
-
104
+ it 'should resume from the saved range reported by the server' do
113
105
  @uploader.chunk_size = 200
114
- @uploader.send_chunk(api_client) # Send bytes 0-199, only 0-99 saved
115
- @uploader.send_chunk(api_client) # Send bytes 100-299
106
+ @uploader.to_http_request # Send bytes 0-199, only 0-99 saved
107
+ @uploader.process_http_response(mock_result(308, 'range' => '0-99'))
108
+ method, url, headers, body = @uploader.to_http_request # Send bytes 100-299
109
+ headers['Content-Range'].should == "bytes 100-299/#{@media.length}"
110
+ headers['Content-length'].should == "200"
116
111
  end
117
112
 
118
113
  it 'should resync the offset after 5xx errors' do
119
- api_client = mock('api')
120
- api_client.should_receive(:execute).and_return(mock_result(500))
121
- api_client.should_receive(:execute).with(
122
- hash_including(:headers => hash_including(
123
- "Content-Range" => "bytes */#{@media.length}",
124
- "Content-Length" => "0"
125
- ))).and_return(mock_result(308, 'range' => '0-99'))
126
- api_client.should_receive(:execute).with(
127
- hash_including(:headers => hash_including(
128
- "Content-Range" => "bytes 100-299/#{@media.length}",
129
- "Content-Length" => "200"
130
- ))).and_return(mock_result(308))
131
-
132
114
  @uploader.chunk_size = 200
133
- @uploader.send_chunk(api_client) # 500, invalidate
134
- @uploader.send_chunk(api_client) # Just resyncs, doesn't actually upload
135
- @uploader.send_chunk(api_client) # Send next chunk at correct range
115
+ @uploader.to_http_request
116
+ @uploader.process_http_response(mock_result(500)) # Invalidates range
117
+ method, url, headers, body = @uploader.to_http_request # Resync
118
+ headers['Content-Range'].should == "bytes */#{@media.length}"
119
+ headers['Content-length'].should == "0"
120
+ @uploader.process_http_response(mock_result(308, 'range' => '0-99'))
121
+ method, url, headers, body = @uploader.to_http_request # Send next chunk at correct range
122
+ headers['Content-Range'].should == "bytes 100-299/#{@media.length}"
123
+ headers['Content-length'].should == "200"
136
124
  end
137
125
 
138
126
  def mock_result(status, headers = {})
@@ -32,7 +32,7 @@ describe Google::APIClient::Result do
32
32
  'maxResults' => 20
33
33
  }
34
34
  })
35
- @request = @reference.to_request
35
+ @request = @reference.to_http_request
36
36
 
37
37
  # Response stub
38
38
  @response = stub("response")
@@ -61,12 +61,12 @@ describe Google::APIClient::Result do
61
61
  "nextLink": "https://www.googleapis.com/plus/v1/people/foo/activities/public?maxResults=20&pageToken=NEXT%2BPAGE%2BTOKEN",
62
62
  "title": "Plus Public Activity Feed for ",
63
63
  "updated": "2012-04-23T00:00:00.000Z",
64
- "id": "tag:google.com,2010:/plus/people/foo/activities/public",
64
+ "id": "123456790",
65
65
  "items": []
66
66
  }
67
67
  END_OF_STRING
68
68
  )
69
- @result = Google::APIClient::Result.new(@reference, @request, @response)
69
+ @result = Google::APIClient::Result.new(@reference, @response)
70
70
  end
71
71
 
72
72
  it 'should indicate a successful response' do
@@ -78,10 +78,11 @@ describe Google::APIClient::Result do
78
78
  end
79
79
 
80
80
  it 'should escape the next page token when calling next_page' do
81
+ pending("This is caused by Faraday's encoding of query parameters.")
81
82
  reference = @result.next_page
82
83
  Hash[reference.parameters].should include('pageToken')
83
84
  Hash[reference.parameters]['pageToken'].should == 'NEXT+PAGE+TOKEN'
84
- url = reference.to_request.to_env(Faraday.default_connection)[:url]
85
+ url = reference.to_env(Faraday.default_connection)[:url]
85
86
  url.to_s.should include('pageToken=NEXT%2BPAGE%2BTOKEN')
86
87
  end
87
88
 
@@ -102,8 +103,7 @@ describe Google::APIClient::Result do
102
103
  'https://www.googleapis.com/plus/v1/people/foo/activities/public?' +
103
104
  'maxResults=20&pageToken=NEXT%2BPAGE%2BTOKEN'
104
105
  @result.data.title.should == 'Plus Public Activity Feed for '
105
- @result.data.id.should ==
106
- 'tag:google.com,2010:/plus/people/foo/activities/public'
106
+ @result.data.id.should == "123456790"
107
107
  @result.data.items.should be_empty
108
108
  end
109
109
  end
@@ -118,12 +118,12 @@ describe Google::APIClient::Result do
118
118
  "selfLink": "https://www.googleapis.com/plus/v1/people/foo/activities/public?",
119
119
  "title": "Plus Public Activity Feed for ",
120
120
  "updated": "2012-04-23T00:00:00.000Z",
121
- "id": "tag:google.com,2010:/plus/people/foo/activities/public",
121
+ "id": "123456790",
122
122
  "items": []
123
123
  }
124
124
  END_OF_STRING
125
125
  )
126
- @result = Google::APIClient::Result.new(@reference, @request, @response)
126
+ @result = Google::APIClient::Result.new(@reference, @response)
127
127
  end
128
128
 
129
129
  it 'should not return a next page token' do
@@ -143,8 +143,7 @@ describe Google::APIClient::Result do
143
143
  @result.data.selfLink.should ==
144
144
  'https://www.googleapis.com/plus/v1/people/foo/activities/public?'
145
145
  @result.data.title.should == 'Plus Public Activity Feed for '
146
- @result.data.id.should ==
147
- 'tag:google.com,2010:/plus/people/foo/activities/public'
146
+ @result.data.id.should == "123456790"
148
147
  @result.data.items.should be_empty
149
148
  end
150
149
  end
@@ -169,7 +168,7 @@ describe Google::APIClient::Result do
169
168
  END_OF_STRING
170
169
  )
171
170
  @response.stub(:status).and_return(400)
172
- @result = Google::APIClient::Result.new(@reference, @request, @response)
171
+ @result = Google::APIClient::Result.new(@reference, @response)
173
172
  end
174
173
 
175
174
  it 'should return error status correctly' do
@@ -179,7 +178,27 @@ describe Google::APIClient::Result do
179
178
  it 'should return the correct error message' do
180
179
  @result.error_message.should == 'Parse Error'
181
180
  end
181
+ end
182
+
183
+ describe 'with 204 No Content response' do
184
+ before do
185
+ @response.stub(:body).and_return('')
186
+ @response.stub(:status).and_return(204)
187
+ @response.stub(:headers).and_return({})
188
+ @result = Google::APIClient::Result.new(@reference, @response)
189
+ end
182
190
 
191
+ it 'should indicate no data is available' do
192
+ @result.data?.should be_false
193
+ end
194
+
195
+ it 'should return nil for data' do
196
+ @result.data.should == nil
197
+ end
198
+
199
+ it 'should return nil for media_type' do
200
+ @result.media_type.should == nil
201
+ end
183
202
  end
184
203
  end
185
204
  end
@@ -17,6 +17,7 @@ require 'spec_helper'
17
17
  require 'google/api_client'
18
18
 
19
19
  describe Google::APIClient::JWTAsserter do
20
+ include ConnectionHelpers
20
21
 
21
22
  before do
22
23
  @key = OpenSSL::PKey::RSA.new 2048
@@ -33,7 +34,7 @@ describe Google::APIClient::JWTAsserter do
33
34
  end
34
35
 
35
36
  it 'should send valid access token request' do
36
- stubs = Faraday::Adapter::Test::Stubs.new do |stub|
37
+ conn = stub_connection do |stub|
37
38
  stub.post('/o/oauth2/token') do |env|
38
39
  params = Addressable::URI.form_unencode(env[:body])
39
40
  JWT.decode(params.assoc("assertion").last, @key.public_key)
@@ -45,14 +46,45 @@ describe Google::APIClient::JWTAsserter do
45
46
  }']
46
47
  end
47
48
  end
48
- connection = Faraday.new(:url => 'https://accounts.google.com') do |builder|
49
- builder.adapter(:test, stubs)
50
- end
51
-
52
49
  asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
53
- auth = asserter.authorize(nil, { :connection => connection})
50
+ auth = asserter.authorize(nil, { :connection => conn })
54
51
  auth.should_not == nil?
55
52
  auth.access_token.should == "1/abcdef1234567890"
53
+ conn.verify
56
54
  end
55
+
56
+ it 'should be refreshable' do
57
+ conn = stub_connection do |stub|
58
+ stub.post('/o/oauth2/token') do |env|
59
+ params = Addressable::URI.form_unencode(env[:body])
60
+ JWT.decode(params.assoc("assertion").last, @key.public_key)
61
+ params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
62
+ [200, {}, '{
63
+ "access_token" : "1/abcdef1234567890",
64
+ "token_type" : "Bearer",
65
+ "expires_in" : 3600
66
+ }']
67
+ end
68
+ stub.post('/o/oauth2/token') do |env|
69
+ params = Addressable::URI.form_unencode(env[:body])
70
+ JWT.decode(params.assoc("assertion").last, @key.public_key)
71
+ params.assoc("grant_type").should == ['grant_type','urn:ietf:params:oauth:grant-type:jwt-bearer']
72
+ [200, {}, '{
73
+ "access_token" : "1/0987654321fedcba",
74
+ "token_type" : "Bearer",
75
+ "expires_in" : 3600
76
+ }']
77
+ end
78
+ end
79
+ asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
80
+ auth = asserter.authorize(nil, { :connection => conn })
81
+ auth.should_not == nil?
82
+ auth.access_token.should == "1/abcdef1234567890"
83
+
84
+ auth.fetch_access_token!(:connection => conn)
85
+ auth.access_token.should == "1/0987654321fedcba"
86
+
87
+ conn.verify
88
+ end
57
89
  end
58
90
 
@@ -14,17 +14,15 @@
14
14
 
15
15
  require 'spec_helper'
16
16
 
17
- gem 'faraday', '~> 0.8.1'
18
17
  require 'faraday'
19
18
  require 'faraday/utils'
20
-
21
- gem 'signet', '~> 0.4.0'
22
19
  require 'signet/oauth_1/client'
23
-
24
20
  require 'google/api_client'
25
21
  require 'google/api_client/version'
26
22
 
27
23
  shared_examples_for 'configurable user agent' do
24
+ include ConnectionHelpers
25
+
28
26
  it 'should allow the user agent to be modified' do
29
27
  client.user_agent = 'Custom User Agent/1.2.3'
30
28
  client.user_agent.should == 'Custom User Agent/1.2.3'
@@ -38,18 +36,14 @@ shared_examples_for 'configurable user agent' do
38
36
  it 'should not allow the user agent to be used with bogus values' do
39
37
  (lambda do
40
38
  client.user_agent = 42
41
- client.transmit(
42
- ['GET', 'http://www.google.com/', [], []]
43
- )
39
+ client.execute(:uri=>'http://www.google.com/')
44
40
  end).should raise_error(TypeError)
45
41
  end
46
42
 
47
43
  it 'should transmit a User-Agent header when sending requests' do
48
44
  client.user_agent = 'Custom User Agent/1.2.3'
49
- request = Faraday::Request.new(:get) do |req|
50
- req.url('http://www.google.com/')
51
- end
52
- stubs = Faraday::Adapter::Test::Stubs.new do |stub|
45
+
46
+ conn = stub_connection do |stub|
53
47
  stub.get('/') do |env|
54
48
  headers = env[:request_headers]
55
49
  headers.should have_key('User-Agent')
@@ -57,15 +51,14 @@ shared_examples_for 'configurable user agent' do
57
51
  [200, {}, ['']]
58
52
  end
59
53
  end
60
- connection = Faraday.new(:url => 'https://www.google.com') do |builder|
61
- builder.adapter(:test, stubs)
62
- end
63
- client.transmit(:request => request, :connection => connection)
64
- stubs.verify_stubbed_calls
54
+ client.execute(:uri=>'http://www.google.com/', :connection => conn)
55
+ conn.verify
65
56
  end
66
57
  end
67
58
 
68
59
  describe Google::APIClient do
60
+ include ConnectionHelpers
61
+
69
62
  let(:client) { Google::APIClient.new }
70
63
 
71
64
  it 'should make its version number available' do
@@ -76,11 +69,18 @@ describe Google::APIClient do
76
69
  Signet::OAuth2::Client.should === client.authorization
77
70
  end
78
71
 
79
- it_should_behave_like 'configurable user agent'
80
-
72
+ describe 'configure for no authentication' do
73
+ before do
74
+ client.authorization = nil
75
+ end
76
+ it_should_behave_like 'configurable user agent'
77
+ end
78
+
81
79
  describe 'configured for OAuth 1' do
82
80
  before do
83
81
  client.authorization = :oauth_1
82
+ client.authorization.token_credential_key = 'abc'
83
+ client.authorization.token_credential_secret = '123'
84
84
  end
85
85
 
86
86
  it 'should use the default OAuth1 client configuration' do
@@ -101,6 +101,7 @@ describe Google::APIClient do
101
101
  describe 'configured for OAuth 2' do
102
102
  before do
103
103
  client.authorization = :oauth_2
104
+ client.authorization.access_token = '12345'
104
105
  end
105
106
 
106
107
  # TODO
@@ -109,31 +110,46 @@ describe Google::APIClient do
109
110
 
110
111
  describe 'when executing requests' do
111
112
  before do
113
+ @prediction = client.discovered_api('prediction', 'v1.2')
112
114
  client.authorization = :oauth_2
113
- @connection = Faraday.new(:url => 'https://www.googleapis.com') do |builder|
114
- stubs = Faraday::Adapter::Test::Stubs.new do |stub|
115
- stub.get('/test') do |env|
116
- env[:request_headers]['Authorization'].should == 'Bearer 12345'
117
- end
115
+ @connection = stub_connection do |stub|
116
+ stub.post('/prediction/v1.2/training?data=12345') do |env|
117
+ env[:request_headers]['Authorization'].should == 'Bearer 12345'
118
118
  end
119
- builder.adapter(:test, stubs)
120
119
  end
121
120
  end
122
-
121
+
122
+ after do
123
+ @connection.verify
124
+ end
125
+
123
126
  it 'should use default authorization' do
124
127
  client.authorization.access_token = "12345"
125
- client.execute(:http_method => :get,
126
- :uri => 'https://www.googleapis.com/test',
127
- :connection => @connection)
128
+ client.execute(
129
+ :api_method => @prediction.training.insert,
130
+ :parameters => {'data' => '12345'},
131
+ :connection => @connection
132
+ )
128
133
  end
129
134
 
130
135
  it 'should use request scoped authorization when provided' do
131
136
  client.authorization.access_token = "abcdef"
132
137
  new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
133
- client.execute(:http_method => :get,
134
- :uri => 'https://www.googleapis.com/test',
135
- :connection => @connection,
136
- :authorization => new_auth)
138
+ client.execute(
139
+ :api_method => @prediction.training.insert,
140
+ :parameters => {'data' => '12345'},
141
+ :authorization => new_auth,
142
+ :connection => @connection
143
+ )
137
144
  end
145
+
146
+ it 'should accept options in array style execute' do
147
+ client.authorization.access_token = "abcdef"
148
+ new_auth = Signet::OAuth2::Client.new(:access_token => '12345')
149
+ client.execute(
150
+ @prediction.training.insert, {'data' => '12345'}, '', {},
151
+ { :authorization => new_auth, :connection => @connection }
152
+ )
153
+ end
138
154
  end
139
155
  end
@@ -2,6 +2,52 @@ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
2
2
  $LOAD_PATH.uniq!
3
3
 
4
4
  require 'rspec'
5
+ require 'faraday'
6
+
7
+ module Faraday
8
+ class Connection
9
+ def verify
10
+ if app.kind_of?(Faraday::Adapter::Test)
11
+ app.stubs.verify_stubbed_calls
12
+ else
13
+ raise TypeError, "Expected test adapter"
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ module ConnectionHelpers
20
+ def stub_connection(&block)
21
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
22
+ block.call(stub)
23
+ end
24
+ connection = Faraday.new do |builder|
25
+ builder.adapter(:test, stubs)
26
+ end
27
+ end
28
+ end
29
+
30
+ module JSONMatchers
31
+ class EqualsJson
32
+ def initialize(expected)
33
+ @expected = JSON.parse(expected)
34
+ end
35
+ def matches?(target)
36
+ @target = JSON.parse(target)
37
+ @target.eql?(@expected)
38
+ end
39
+ def failure_message
40
+ "expected #{@target.inspect} to be #{@expected}"
41
+ end
42
+ def negative_failure_message
43
+ "expected #{@target.inspect} not to be #{@expected}"
44
+ end
45
+ end
46
+
47
+ def be_json(expected)
48
+ EqualsJson.new(expected)
49
+ end
50
+ end
5
51
 
6
52
  RSpec.configure do |config|
7
53
  end