koala 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ v0.7.3
2
+ -- Added support for picture sizes -- thanks thhermansen for the patch!
3
+ -- Adjusted the return values for several methods (get_access_token, get_app_access_token, get_token_from_session_key, get_tokens_from_session_keys, get_user_from_cookies)
4
+ -- These methods now return strings, rather than hashes, which makes more sense
5
+ -- The strings are overloaded with an [] method for backwards compatibility (Ruby is truly amazing)
6
+ -- Using those methods triggers a deprecation warning
7
+ -- This will be removed by 1.0
8
+ -- There are new info methods (get_access_token_info, get_app_access_token_info, get_token_info_from_session_keys, and get_user_info_from_cookies) that natively return hashes, for when you want the expiration date
9
+ -- Responses with HTTP status 500+ now properly throw errors under Net::HTTP
10
+ -- Updated changelog
11
+ -- Added license and copyright
12
+
1
13
  v0.7.2
2
14
  -- Added support for exchanging session keys for OAuth access tokens (get_token_from_session_key for single keys, get_tokens_from_session_keys for multiple)
3
15
  -- Moved Koala files into a koala/ subdirectory to minimize risk of name collisions
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2010 Alex Koppel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest CHANGED
@@ -1,4 +1,5 @@
1
1
  CHANGELOG
2
+ LICENSE
2
3
  Manifest
3
4
  Rakefile
4
5
  examples/oauth_playground/Capfile
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'rake'
4
4
  require 'echoe'
5
5
 
6
6
  # gem management
7
- Echoe.new('koala', '0.7.2') do |p|
7
+ Echoe.new('koala', '0.7.3') do |p|
8
8
  p.summary = "A lightweight, flexible library for Facebook with support for the Graph API, the old REST API, realtime updates, and OAuth validation."
9
9
  p.description = "Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph API and the older REST API, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services."
10
10
  p.url = "http://github.com/arsduo/koala"
@@ -12,4 +12,5 @@ Echoe.new('koala', '0.7.2') do |p|
12
12
  p.email = "alex@alexkoppel.com"
13
13
  p.ignore_pattern = ["tmp/*", "script/*", "pkg/*"]
14
14
  p.development_dependencies = []
15
+ p.retain_gemspec = true
15
16
  end
@@ -1,13 +1,13 @@
1
1
  development:
2
- api_key:
3
- secret_key:
4
- app_id:
2
+ api_key: 171e3563d4fee42e0ba27450838bba32
3
+ secret_key: c81302ccef57cbdd2e68b2229e54cd2f
4
+ app_id: 119347844754245
5
5
 
6
6
  test:
7
7
  api_key:
8
8
  secret_key:
9
9
 
10
10
  production:
11
- api_key:
12
- secret_key:
13
- app_id:
11
+ api_key: 25e1cec0df2b3bfa781da3ed78da3a1e
12
+ secret_key: e45e55a333eec232d4206d2703de1307
13
+ app_id: 119908831367602
data/koala.gemspec CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{koala}
5
- s.version = "0.7.2"
5
+ s.version = "0.7.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional"]
9
- s.date = %q{2010-06-02}
9
+ s.date = %q{2010-06-22}
10
10
  s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph API and the older REST API, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.}
11
11
  s.email = %q{alex@alexkoppel.com}
12
- s.extra_rdoc_files = ["CHANGELOG", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb"]
13
- s.files = ["CHANGELOG", "Manifest", "Rakefile", "examples/oauth_playground/Capfile", "examples/oauth_playground/LICENSE", "examples/oauth_playground/Rakefile", "examples/oauth_playground/config.ru", "examples/oauth_playground/config/deploy.rb", "examples/oauth_playground/config/facebook.yml", "examples/oauth_playground/lib/load_facebook.rb", "examples/oauth_playground/lib/oauth_playground.rb", "examples/oauth_playground/readme.md", "examples/oauth_playground/spec/oauth_playground_spec.rb", "examples/oauth_playground/spec/spec_helper.rb", "examples/oauth_playground/tmp/restart.txt", "examples/oauth_playground/views/index.erb", "examples/oauth_playground/views/layout.erb", "init.rb", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb", "readme.md", "spec/facebook_data.yml", "spec/koala/api_base_tests.rb", "spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb", "spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb", "spec/koala/graph_api/graph_api_no_access_token_tests.rb", "spec/koala/graph_api/graph_api_with_access_token_tests.rb", "spec/koala/live_testing_data_helper.rb", "spec/koala/net_http_service_tests.rb", "spec/koala/oauth/oauth_tests.rb", "spec/koala/realtime_updates/realtime_updates_tests.rb", "spec/koala/rest_api/rest_api_no_access_token_tests.rb", "spec/koala/rest_api/rest_api_with_access_token_tests.rb", "spec/koala_spec.rb", "spec/koala_spec_helper.rb", "spec/koala_spec_without_mocks.rb", "spec/mock_facebook_responses.yml", "spec/mock_http_service.rb", "koala.gemspec"]
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "Rakefile", "examples/oauth_playground/Capfile", "examples/oauth_playground/LICENSE", "examples/oauth_playground/Rakefile", "examples/oauth_playground/config.ru", "examples/oauth_playground/config/deploy.rb", "examples/oauth_playground/config/facebook.yml", "examples/oauth_playground/lib/load_facebook.rb", "examples/oauth_playground/lib/oauth_playground.rb", "examples/oauth_playground/readme.md", "examples/oauth_playground/spec/oauth_playground_spec.rb", "examples/oauth_playground/spec/spec_helper.rb", "examples/oauth_playground/tmp/restart.txt", "examples/oauth_playground/views/index.erb", "examples/oauth_playground/views/layout.erb", "init.rb", "lib/koala.rb", "lib/koala/graph_api.rb", "lib/koala/http_services.rb", "lib/koala/realtime_updates.rb", "lib/koala/rest_api.rb", "readme.md", "spec/facebook_data.yml", "spec/koala/api_base_tests.rb", "spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb", "spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb", "spec/koala/graph_api/graph_api_no_access_token_tests.rb", "spec/koala/graph_api/graph_api_with_access_token_tests.rb", "spec/koala/live_testing_data_helper.rb", "spec/koala/net_http_service_tests.rb", "spec/koala/oauth/oauth_tests.rb", "spec/koala/realtime_updates/realtime_updates_tests.rb", "spec/koala/rest_api/rest_api_no_access_token_tests.rb", "spec/koala/rest_api/rest_api_with_access_token_tests.rb", "spec/koala_spec.rb", "spec/koala_spec_helper.rb", "spec/koala_spec_without_mocks.rb", "spec/mock_facebook_responses.yml", "spec/mock_http_service.rb", "koala.gemspec"]
14
14
  s.homepage = %q{http://github.com/arsduo/koala}
15
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala", "--main", "readme.md"]
16
16
  s.require_paths = ["lib"]
data/lib/koala.rb CHANGED
@@ -52,6 +52,11 @@ module Koala
52
52
  # make the request via the provided service
53
53
  result = Koala.make_request(path, args, verb, options)
54
54
 
55
+ # Check for any 500 errors before parsing the body
56
+ # since we're not guaranteed that the body is valid JSON
57
+ # in the case of a server error
58
+ raise APIError.new({"type" => "HTTP #{result.status.to_s}", "message" => "Response body: #{result.body}"}) if result.status >= 500
59
+
55
60
  # Parse the body as JSON and check for errors if provided a mechanism to do so
56
61
  # Note: Facebook sometimes sends results like "true" and "false", which aren't strictly objects
57
62
  # and cause JSON.parse to fail -- so we account for that by wrapping the result in []
@@ -103,11 +108,10 @@ module Koala
103
108
  @oauth_callback_url = oauth_callback_url
104
109
  end
105
110
 
106
- def get_user_from_cookie(cookie_hash)
111
+ def get_user_info_from_cookie(cookie_hash)
107
112
  # Parses the cookie set by the official Facebook JavaScript SDK.
108
113
  #
109
- # cookies should be a dictionary-like object mapping cookie names to
110
- # cookie values.
114
+ # cookies should be a Hash, like the one Rails provides
111
115
  #
112
116
  # If the user is logged in via Facebook, we return a dictionary with the
113
117
  # keys "uid" and "access_token". The former is the user's Facebook ID,
@@ -132,8 +136,20 @@ module Koala
132
136
  sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
133
137
  end
134
138
  end
139
+ alias_method :get_user_info_from_cookies, :get_user_info_from_cookie
140
+
141
+ def get_user_from_cookie(cookies)
142
+ # overload this to be backward compatible with older implementations
143
+ # icky ruby magic, but it's _really_ cool we can do this
144
+ info = get_user_info_from_cookies(cookies)
145
+ string = info["uid"]
146
+
147
+ overload_as_hash(string, info)
148
+ end
135
149
  alias_method :get_user_from_cookies, :get_user_from_cookie
136
150
 
151
+ # URLs
152
+
137
153
  def url_for_oauth_code(options = {})
138
154
  # for permissions, see http://developers.facebook.com/docs/authentication/permissions
139
155
  permissions = options[:permissions]
@@ -157,18 +173,34 @@ module Koala
157
173
  "https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
158
174
  end
159
175
 
160
- def get_access_token(code)
176
+ def get_access_token_info(code)
161
177
  # convenience method to get a parsed token from Facebook for a given code
162
178
  # should this require an OAuth callback URL?
163
179
  get_token_from_server(:code => code, :redirect_uri => @oauth_callback_url)
164
180
  end
165
181
 
166
- def get_app_access_token
182
+ def get_access_token(code)
183
+ info = get_access_token_info(code)
184
+ # upstream methods will throw errors if needed
185
+ string = info["access_token"]
186
+
187
+ overload_as_hash(string, info)
188
+ end
189
+
190
+ def get_app_access_token_info
167
191
  # convenience method to get a the application's sessionless access token
168
192
  get_token_from_server({:type => 'client_cred'}, true)
169
193
  end
170
194
 
171
- def get_tokens_from_session_keys(sessions)
195
+ def get_app_access_token
196
+ info = get_app_access_token_info
197
+ string = info["access_token"]
198
+
199
+ overload_as_hash(string, info)
200
+ end
201
+
202
+ # from session keys
203
+ def get_token_info_from_session_keys(sessions)
172
204
  # fetch the OAuth tokens from Facebook
173
205
  response = fetch_token_string({
174
206
  :type => 'client_cred',
@@ -184,8 +216,21 @@ module Koala
184
216
  JSON.parse(response)
185
217
  end
186
218
 
219
+ def get_tokens_from_session_keys(sessions)
220
+ # get the original hash results
221
+ results = get_token_info_from_session_keys(sessions)
222
+ # now recollect them as backward-compatible strings
223
+ # for easier use
224
+ results.collect do |r|
225
+ string = r["access_token"]
226
+
227
+ overload_as_hash string, r
228
+ end
229
+ end
230
+
187
231
  def get_token_from_session_key(session)
188
232
  # convenience method for a single key
233
+ # gets the overlaoded strings automatically
189
234
  get_tokens_from_session_keys([session])[0]
190
235
  end
191
236
 
@@ -216,6 +261,23 @@ module Koala
216
261
  :client_secret => @app_secret
217
262
  }.merge!(args), post ? "post" : "get").body
218
263
  end
264
+
265
+ # overload the object to be accessible as a hash
266
+ # used to make get_*_token methods backward compatible
267
+ # icky ruby magic, but it's _really_ cool we can do this
268
+ def overload_as_hash(obj, hash)
269
+ command = <<-EOS
270
+ def [](index)
271
+ puts "WARNING: get_app_access_token now provides the access token as a string; use get_app_access_token_info if you want the hash with expirations. Otherwise you no longer need to call [] to get the token itself."
272
+ hash = #{hash.inspect}
273
+ hash[index]
274
+ end
275
+ EOS
276
+
277
+ (class << obj; self; end).class_eval command
278
+
279
+ obj
280
+ end
219
281
  end
220
282
  end
221
283
 
@@ -47,11 +47,11 @@ module Koala
47
47
  graph_call("#{id}/#{connection_name}", args)["data"]
48
48
  end
49
49
 
50
- def get_picture(object)
51
- result = graph_call("#{object}/picture", {}, "get", :http_component => :headers)
50
+ def get_picture(object, args = {})
51
+ result = graph_call("#{object}/picture", args, "get", :http_component => :headers)
52
52
  result["Location"]
53
- end
54
-
53
+ end
54
+
55
55
  def put_object(parent_object, connection_name, args = {})
56
56
  # Writes the given object to the graph, connected to the given parent.
57
57
  #
@@ -5,18 +5,18 @@
5
5
 
6
6
  # You must supply this value yourself to test the GraphAPI class.
7
7
  # Your OAuth token should have publish_stream and read_stream permissions.
8
- oauth_token: 119908831367602|2.r_nk_Ghvmy2OVfCqc2xD5w__.3600.1275534000-2905623|uRgZZ9WrZL7sBmS2f02G7UpMFZg.
8
+ oauth_token:
9
9
 
10
10
  # for testing the OAuth class
11
11
  # baseline app
12
12
  oauth_test_data:
13
13
  # You must supply this value yourself, since they will expire.
14
- code: 2.r_nk_Ghvmy2OVfCqc2xD5w__.3600.1275534000-2905623|4nUNPLdAgG0Q7PauPJ00TffIB88.
14
+ code:
15
15
  # easiest way to get session keys: use multiple test accounts with the Javascript login at http://oauth.twoalex.com
16
- session_key: 2.r_nk_Ghvmy2OVfCqc2xD5w__.3600.1275534000-2905623
16
+ session_key:
17
17
  multiple_session_keys:
18
- - 2.r_nk_Ghvmy2OVfCqc2xD5w__.3600.1275534000-2905623
19
- - 2.r_nk2_Ghvmy2OVfCqc2xD5w__.3600.1275534000-2905623
18
+ -
19
+ -
20
20
 
21
21
  # These values will work out of the box
22
22
  app_id: 119908831367602
@@ -29,9 +29,45 @@ class ApiBaseTests < Test::Unit::TestCase
29
29
  service.api('anything')
30
30
  end
31
31
 
32
- it "should properly handle the http_component parameter"
32
+ it "should get the attribute of a Koala::Response given by the http_component parameter" do
33
+ http_component = :method_name
34
+
35
+ response = mock('Mock KoalaResponse', :body => '', :status => 200)
36
+ response.should_receive(http_component).and_return('')
37
+
38
+ Koala.stub(:make_request).and_return(response)
39
+
40
+ @service.api('anything', 'get', {}, :http_component => http_component)
41
+ end
33
42
 
34
- it "should execute a block to test for errors if passed one"
43
+ it "should return the body of the request as JSON if no http_component is given" do
44
+ response = stub('response', :body => 'body', :status => 200)
45
+ Koala.stub(:make_request).and_return(response)
46
+
47
+ json_body = mock('JSON body')
48
+ JSON.stub(:parse).and_return([json_body])
49
+
50
+ @service.api('anything').should == json_body
51
+ end
52
+
53
+ it "should execute a block with the response body if passed one" do
54
+ body = '{}'
55
+ Koala.stub(:make_request).and_return(Koala::Response.new(200, body, {}))
56
+
57
+ yield_test = mock('Yield Tester')
58
+ yield_test.should_receive(:pass)
59
+
60
+ @service.api('anything') do |arg|
61
+ yield_test.pass
62
+ arg.should == JSON.parse(body)
63
+ end
64
+ end
65
+
66
+ it "should raise an API error if the HTTP response code is greater than or equal to 500" do
67
+ Koala.stub(:make_request).and_return(Koala::Response.new(500, 'response body', {}))
68
+
69
+ lambda { @service.api('anything') }.should raise_exception(Koala::Facebook::APIError)
70
+ end
35
71
 
36
72
  it "should handle rogue true/false as responses" do
37
73
  Koala.should_receive(:make_request).and_return(Koala::Response.new(200, 'true', {}))
@@ -41,4 +77,35 @@ class ApiBaseTests < Test::Unit::TestCase
41
77
  @service.api('anything').should be_false
42
78
  end
43
79
  end
80
+ end
81
+
82
+ shared_examples_for "methods that return overloaded strings" do
83
+ before :each do
84
+ @key ||= "access_token"
85
+ end
86
+
87
+ it "should be overloaded to be backward compatible" do
88
+ @result.respond_to?(:[]).should be_true
89
+ end
90
+
91
+ it "should allow hash access to the access token info" do
92
+ @result[@key].should == @result
93
+ end
94
+
95
+ it "should output a deprecation warning when the result is used as a hash" do
96
+ out = nil
97
+
98
+ begin
99
+ # we want to capture the deprecation warning as well as the output
100
+ # credit to http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/ for the technique
101
+ out = StringIO.new
102
+ $stdout = out
103
+ @result[@key]
104
+ ensure
105
+ $stdout = STDOUT
106
+ end
107
+
108
+ # ensure we got a warning
109
+ out.should_not be_nil
110
+ end
44
111
  end
@@ -34,6 +34,10 @@ shared_examples_for "Koala GraphAPI without an access token" do
34
34
  @api.get_picture("chris.baclig").should =~ /http\:\/\//
35
35
  end
36
36
 
37
+ it "should be able to access a user's picture, given a picture type" do
38
+ @api.get_picture("chris.baclig", {:type => 'large'}).should =~ /^http\:\/\//
39
+ end
40
+
37
41
  it "should be able to access connections from public Pages" do
38
42
  result = @api.get_connections("contextoptional", "likes")
39
43
  result.should be_a(Array)
@@ -31,6 +31,10 @@ it "should get public data about a user" do
31
31
  @api.get_picture("chris.baclig").should =~ /http\:\/\//
32
32
  end
33
33
 
34
+ it "should be able to access a user's picture, given a picture type" do
35
+ @api.get_picture("chris.baclig", {:type => 'large'}).should =~ /^http\:\/\//
36
+ end
37
+
34
38
  it "should be able to access connections from users" do
35
39
  result = @api.get_connections("lukeshepard", "likes")
36
40
  result.length.should > 0
@@ -8,10 +8,174 @@ class NetHTTPServiceTests < Test::Unit::TestCase
8
8
  it "should define a make_request static module method" do
9
9
  Bear.respond_to?(:make_request).should be_true
10
10
  end
11
-
12
- it "should return a string for location header"
13
11
 
14
- it "should use POST if verb is not GET"
12
+ describe "when making a request" do
13
+ before(:each) do
14
+ # Setup stubs for make_request to execute without exceptions
15
+ @mock_http_response = stub('Net::HTTPResponse', :code => 1)
16
+ @mock_body = stub('Net::HTTPResponse body')
17
+ @http_request_result = [@mock_http_response, @mock_body]
18
+
19
+ @http_yield_mock = mock('Net::HTTP start yielded object')
20
+
21
+ @http_yield_mock.stub(:post).and_return(@http_request_result)
22
+ @http_yield_mock.stub(:get).and_return(@http_request_result)
23
+
24
+ @http_mock = stub('Net::HTTP object', 'use_ssl=' => true, 'verify_mode=' => true)
25
+ @http_mock.stub(:start).and_yield(@http_yield_mock)
26
+
27
+ Net::HTTP.stub(:new).and_return(@http_mock)
28
+ end
29
+
30
+ it "should use POST if verb is not GET" do
31
+ @http_yield_mock.should_receive(:post).and_return(@mock_http_response)
32
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
33
+
34
+ Bear.make_request('anything', {}, 'anything')
35
+ end
36
+
37
+ it "should use port 443" do
38
+ Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
39
+
40
+ Bear.make_request('anything', {}, 'anything')
41
+ end
42
+
43
+ it "should use SSL" do
44
+ @http_mock.should_receive('use_ssl=').with(true)
45
+
46
+ Bear.make_request('anything', {}, 'anything')
47
+ end
48
+
49
+ it "should use the graph server by default" do
50
+ Net::HTTP.should_receive(:new).with(Koala::Facebook::GRAPH_SERVER, anything).and_return(@http_mock)
51
+ Bear.make_request('anything', {}, 'anything')
52
+ end
53
+
54
+ it "should use the REST server if the :rest_api option is true" do
55
+ Net::HTTP.should_receive(:new).with(Koala::Facebook::REST_SERVER, anything).and_return(@http_mock)
56
+ Bear.make_request('anything', {}, 'anything', :rest_api => true)
57
+ end
58
+
59
+ it "should turn off vertificate validaiton warnings" do
60
+ @http_mock.should_receive('verify_mode=').with(OpenSSL::SSL::VERIFY_NONE)
61
+
62
+ Bear.make_request('anything', {}, 'anything')
63
+ end
64
+
65
+ it "should start an HTTP connection" do
66
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
67
+ Bear.make_request('anything', {}, 'anything')
68
+ end
69
+
70
+ describe "via POST" do
71
+ it "should use Net::HTTP to make a POST request" do
72
+ @http_yield_mock.should_receive(:post).and_return(@http_request_result)
73
+
74
+ Bear.make_request('anything', {}, 'post')
75
+ end
76
+
77
+ it "should go to the specified path" do
78
+ path = mock('Path')
79
+ @http_yield_mock.should_receive(:post).with(path, anything).and_return(@http_request_result)
80
+
81
+ Bear.make_request(path, {}, 'post')
82
+ end
83
+
84
+ it "should use encoded parameters" do
85
+ args = {}
86
+ params = mock('Encoded parameters')
87
+ Bear.should_receive(:encode_params).with(args).and_return(params)
88
+
89
+ @http_yield_mock.should_receive(:post).with(anything, params).and_return(@http_request_result)
90
+
91
+ Bear.make_request('anything', args, 'post')
92
+ end
93
+ end
94
+
95
+ describe "via GET" do
96
+ it "should use Net::HTTP to make a GET request" do
97
+ @http_yield_mock.should_receive(:get).and_return(@http_request_result)
98
+
99
+ Bear.make_request('anything', {}, 'get')
100
+ end
101
+
102
+ it "should use the correct path, including arguments" do
103
+ path = mock('Path')
104
+ params = mock('Encoded parameters')
105
+ args = {}
106
+
107
+ Bear.should_receive(:encode_params).with(args).and_return(params)
108
+ @http_yield_mock.should_receive(:get).with("#{path}?#{params}").and_return(@http_request_result)
109
+
110
+ Bear.make_request(path, args, 'get')
111
+ end
112
+ end
113
+
114
+ describe "the returned value" do
115
+ before(:each) do
116
+ @response = Bear.make_request('anything', {}, 'anything')
117
+ end
118
+
119
+ it "should return a Koala::Response object" do
120
+ @response.class.should == Koala::Response
121
+ end
122
+
123
+ it "should return a Koala::Response with the right status" do
124
+ @response.status.should == @mock_http_response.code
125
+ end
126
+
127
+ it "should reutrn a Koala::Response with the right body" do
128
+ @response.body.should == @mock_body
129
+ end
130
+
131
+ it "should return a Koala::Response with the Net::HTTPResponse object as headers" do
132
+ @response.headers.should == @mock_http_response
133
+ end
134
+ end # describe return value
135
+ end # describe when making a request
15
136
 
16
- it "should return a Koala::Response object"
137
+ describe "when encoding parameters" do
138
+ it "should return an empty string if param_hash evaluates to false" do
139
+ Bear.encode_params(nil).should == ''
140
+ end
141
+
142
+ it "should convert values to JSON if the value is not a String" do
143
+ val = 'json_value'
144
+ not_a_string = 'not_a_string'
145
+ not_a_string.stub(:class).and_return('NotAString')
146
+ not_a_string.should_receive(:to_json).and_return(val)
147
+
148
+ string = "hi"
149
+
150
+ args = {
151
+ not_a_string => not_a_string,
152
+ string => string
153
+ }
154
+
155
+ result = Bear.encode_params(args)
156
+ result.split('&').find do |key_and_val|
157
+ key_and_val.match("#{not_a_string}=#{val}")
158
+ end.should be_true
159
+ end
160
+
161
+ it "should escape all values" do
162
+ args = Hash[*(1..4).map {|i| [i.to_s, "Value #{i}($"]}.flatten]
163
+
164
+ result = Bear.encode_params(args)
165
+ result.split('&').each do |key_val|
166
+ key, val = key_val.split('=')
167
+ val.should == CGI.escape(args[key])
168
+ end
169
+ end
170
+
171
+ it "should convert all keys to Strings" do
172
+ args = Hash[*(1..4).map {|i| [i, "val#{i}"]}.flatten]
173
+
174
+ result = Bear.encode_params(args)
175
+ result.split('&').each do |key_val|
176
+ key, val = key_val.split('=')
177
+ key.should == args.find{|key_val_arr| key_val_arr.last == val}.first.to_s
178
+ end
179
+ end
180
+ end
17
181
  end
@@ -51,41 +51,66 @@ class FacebookOAuthTests < Test::Unit::TestCase
51
51
  @oauth.oauth_callback_url == nil).should be_true
52
52
  end
53
53
 
54
- # cookie parsing
55
- it "should properly parse valid cookies" do
56
- result = @oauth.get_user_from_cookie(@oauth_data["valid_cookies"])
57
- result["uid"].should
58
- end
54
+ describe "cookie parsing" do
55
+ describe "get_user_info_from_cookies" do
56
+ it "should properly parse valid cookies" do
57
+ result = @oauth.get_user_info_from_cookies(@oauth_data["valid_cookies"])
58
+ result.should be_a(Hash)
59
+ end
59
60
 
60
- it "should return all the cookie components from valid cookie string" do
61
- cookie_data = @oauth_data["valid_cookies"]
62
- parsing_results = @oauth.get_user_from_cookie(cookie_data)
63
- number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
64
- parsing_results.length.should == number_of_components
65
- end
61
+ it "should return all the cookie components from valid cookie string" do
62
+ cookie_data = @oauth_data["valid_cookies"]
63
+ parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
64
+ number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
65
+ parsing_results.length.should == number_of_components
66
+ end
66
67
 
67
- it "should properly parse valid offline access cookies (e.g. no expiration)" do
68
- result = @oauth.get_user_from_cookie(@oauth_data["offline_access_cookies"])
69
- result["uid"].should
70
- end
68
+ it "should properly parse valid offline access cookies (e.g. no expiration)" do
69
+ result = @oauth.get_user_info_from_cookies(@oauth_data["offline_access_cookies"])
70
+ result["uid"].should
71
+ end
71
72
 
72
- it "should return all the cookie components from offline access cookies" do
73
- cookie_data = @oauth_data["offline_access_cookies"]
74
- parsing_results = @oauth.get_user_from_cookie(cookie_data)
75
- number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
76
- parsing_results.length.should == number_of_components
77
- end
73
+ it "should return all the cookie components from offline access cookies" do
74
+ cookie_data = @oauth_data["offline_access_cookies"]
75
+ parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
76
+ number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
77
+ parsing_results.length.should == number_of_components
78
+ end
78
79
 
79
- it "shouldn't parse expired cookies" do
80
- result = @oauth.get_user_from_cookie(@oauth_data["expired_cookies"])
81
- result.should be_nil
82
- end
80
+ it "shouldn't parse expired cookies" do
81
+ result = @oauth.get_user_info_from_cookies(@oauth_data["expired_cookies"])
82
+ result.should be_nil
83
+ end
83
84
 
84
- it "shouldn't parse invalid cookies" do
85
- # make an invalid string by replacing some values
86
- bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
87
- result = @oauth.get_user_from_cookie(bad_cookie_hash)
88
- result.should be_nil
85
+ it "shouldn't parse invalid cookies" do
86
+ # make an invalid string by replacing some values
87
+ bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
88
+ result = @oauth.get_user_info_from_cookies(bad_cookie_hash)
89
+ result.should be_nil
90
+ end
91
+ end
92
+
93
+ describe "get_user_from_cookies" do
94
+ it "should use get_user_info_from_cookies to parse the cookies" do
95
+ data = @oauth_data["valid_cookies"]
96
+ @oauth.should_receive(:get_user_info_from_cookies).with(data).and_return({})
97
+ @oauth.get_user_from_cookies(data)
98
+ end
99
+
100
+ it "should use return a string" do
101
+ result = @oauth.get_user_from_cookies(@oauth_data["valid_cookies"])
102
+ result.should be_a(String)
103
+ end
104
+
105
+ describe "backward compatibility" do
106
+ before :each do
107
+ @result = @oauth.get_user_from_cookies(@oauth_data["valid_cookies"])
108
+ @key = "uid"
109
+ end
110
+
111
+ it_should_behave_like "methods that return overloaded strings"
112
+ end
113
+ end
89
114
  end
90
115
 
91
116
  # OAuth URLs
@@ -157,46 +182,149 @@ class FacebookOAuthTests < Test::Unit::TestCase
157
182
  out.should_not be_nil
158
183
  end
159
184
 
160
- # get_access_token
161
- it "should properly get and parse an access token token results" do
162
- result = @oauth.get_access_token(@code)
163
- result["access_token"].should
185
+ describe "get_access_token_info" do
186
+ it "should properly get and parse an access token token results into a hash" do
187
+ result = @oauth.get_access_token_info(@code)
188
+ result.should be_a(Hash)
189
+ end
190
+
191
+ it "should properly include the access token results" do
192
+ result = @oauth.get_access_token_info(@code)
193
+ result["access_token"].should
194
+ end
195
+
196
+ it "should raise an error when get_access_token is called with a bad code" do
197
+ lambda { @oauth.get_access_token_info("foo") }.should raise_error(Koala::Facebook::APIError)
198
+ end
164
199
  end
165
200
 
166
- it "should raise an error when get_access_token is called with a bad code" do
167
- lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::APIError)
201
+ describe "get_access_token" do
202
+ it "should use get_access_token_info to get and parse an access token token results" do
203
+ result = @oauth.get_access_token(@code)
204
+ result.should be_a(String)
205
+ end
206
+
207
+ it "should return the access token as a string" do
208
+ result = @oauth.get_access_token(@code)
209
+ original = @oauth.get_access_token_info(@code)
210
+ result.should == original["access_token"]
211
+ end
212
+
213
+ it "should raise an error when get_access_token is called with a bad code" do
214
+ lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::APIError)
215
+ end
216
+
217
+ describe "backwards compatibility" do
218
+ before :each do
219
+ @result = @oauth.get_access_token(@code)
220
+ end
221
+
222
+ it_should_behave_like "methods that return overloaded strings"
223
+ end
168
224
  end
225
+
226
+ describe "get_app_access_token_info" do
227
+ it "should properly get and parse an app's access token as a hash" do
228
+ result = @oauth.get_app_access_token_info
229
+ result.should be_a(Hash)
230
+ end
169
231
 
170
- # get_app_access_token
171
-
172
- it "should properly get and parse an app's access token token results" do
173
- result = @oauth.get_app_access_token
174
- result["access_token"].should
232
+ it "should include the access token" do
233
+ result = @oauth.get_app_access_token_info
234
+ result["access_token"].should
235
+ end
175
236
  end
237
+
238
+ describe "get_app_acess_token" do
239
+ it "should use get_access_token_info to get and parse an access token token results" do
240
+ result = @oauth.get_app_access_token
241
+ result.should be_a(String)
242
+ end
176
243
 
177
- # get_tokens_from_session_keys
178
- it "should get an array of session keys from Facebook when passed a single key" do
179
- result = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
180
- result.should be_an(Array)
181
- result.length.should == 1
244
+ it "should return the access token as a string" do
245
+ result = @oauth.get_app_access_token
246
+ original = @oauth.get_app_access_token_info
247
+ result.should == original["access_token"]
248
+ end
249
+
250
+ describe "backwards compatibility" do
251
+ before :each do
252
+ @result = @oauth.get_app_access_token
253
+ end
254
+
255
+ it_should_behave_like "methods that return overloaded strings"
256
+ end
182
257
  end
183
258
 
184
- it "should get an array of session keys from Facebook when passed multiple keys" do
185
- result = @oauth.get_tokens_from_session_keys(@oauth_data["multiple_session_keys"])
186
- result.should be_an(Array)
187
- result.length.should == 2
188
- end
259
+ describe "exchanging session keys" do
260
+ describe "with get_token_info_from_session_keys" do
261
+ it "should get an array of session keys from Facebook when passed a single key" do
262
+ result = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
263
+ result.should be_an(Array)
264
+ result.length.should == 1
265
+ end
189
266
 
190
- # get_token_from_session_key
191
- it "should call get_tokens_from_session_keys when the get_token_from_session_key is called" do
192
- key = @oauth_data["session_key"]
193
- @oauth.should_receive(:get_tokens_from_session_keys).with([key]).and_return([])
194
- @oauth.get_token_from_session_key(key)
195
- end
196
-
197
- it "should get back a hash from get_token_from_session_key" do
198
- result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
199
- result["access_token"].should
267
+ it "should get an array of session keys from Facebook when passed multiple keys" do
268
+ result = @oauth.get_tokens_from_session_keys(@oauth_data["multiple_session_keys"])
269
+ result.should be_an(Array)
270
+ result.length.should == 2
271
+ end
272
+
273
+ it "should return the original hashes" do
274
+ result = @oauth.get_token_info_from_session_keys(@oauth_data["multiple_session_keys"])
275
+ result[0].should be_a(Hash)
276
+ end
277
+ end
278
+
279
+ describe "with get_tokens_from_session_keys" do
280
+ it "should call get_token_info_from_session_keys" do
281
+ args = @oauth_data["multiple_session_keys"]
282
+ @oauth.should_receive(:get_token_info_from_session_keys).with(args).and_return([])
283
+ @oauth.get_tokens_from_session_keys(args)
284
+ end
285
+
286
+ it "should return an array of strings" do
287
+ args = @oauth_data["multiple_session_keys"]
288
+ result = @oauth.get_tokens_from_session_keys(args)
289
+ result.each {|r| r.should be_a(String) }
290
+ end
291
+
292
+ describe "backwards compatibility" do
293
+ before :each do
294
+ args = @oauth_data["multiple_session_keys"]
295
+ @result = @oauth.get_tokens_from_session_keys(args)[0]
296
+ end
297
+
298
+ it_should_behave_like "methods that return overloaded strings"
299
+ end
300
+ end
301
+
302
+ describe "get_token_from_session_key" do
303
+ it "should call get_tokens_from_session_keys when the get_token_from_session_key is called" do
304
+ key = @oauth_data["session_key"]
305
+ @oauth.should_receive(:get_tokens_from_session_keys).with([key]).and_return([])
306
+ @oauth.get_token_from_session_key(key)
307
+ end
308
+
309
+ it "should get back the access token string from get_token_from_session_key" do
310
+ result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
311
+ result.should be_a(String)
312
+ end
313
+
314
+ it "should be the first value in the array" do
315
+ result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
316
+ array = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
317
+ result.should == array[0]
318
+ end
319
+
320
+ describe "backwards compatibility" do
321
+ before :each do
322
+ @result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
323
+ end
324
+
325
+ it_should_behave_like "methods that return overloaded strings"
326
+ end
327
+ end
200
328
  end
201
329
 
202
330
  # protected methods
@@ -114,6 +114,18 @@ graph_api:
114
114
  code: 302
115
115
  headers:
116
116
  Location: http://facebook.com/
117
+ type=large:
118
+ get:
119
+ no_token:
120
+ code: 302
121
+ headers:
122
+ Location: http://facebook.com/large
123
+ with_token:
124
+ code: 302
125
+ headers:
126
+ Location: http://facebook.com/large
127
+
128
+
117
129
  search:
118
130
  q=facebook:
119
131
  get:
@@ -1,4 +1,5 @@
1
1
  require 'erb'
2
+ require 'yaml'
2
3
 
3
4
  module Koala
4
5
  module MockHTTPService
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 2
9
- version: 0.7.2
8
+ - 3
9
+ version: 0.7.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-02 00:00:00 -07:00
17
+ date: 2010-06-22 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -26,6 +26,7 @@ extensions: []
26
26
 
27
27
  extra_rdoc_files:
28
28
  - CHANGELOG
29
+ - LICENSE
29
30
  - lib/koala.rb
30
31
  - lib/koala/graph_api.rb
31
32
  - lib/koala/http_services.rb
@@ -33,6 +34,7 @@ extra_rdoc_files:
33
34
  - lib/koala/rest_api.rb
34
35
  files:
35
36
  - CHANGELOG
37
+ - LICENSE
36
38
  - Manifest
37
39
  - Rakefile
38
40
  - examples/oauth_playground/Capfile