koala 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -0
- data/Manifest +1 -1
- data/Rakefile +2 -2
- data/init.rb +1 -1
- data/koala.gemspec +4 -4
- data/lib/http_services.rb +1 -1
- data/lib/koala.rb +47 -12
- data/readme.md +4 -2
- data/test/facebook_data.yml +27 -8
- data/test/koala/facebook_oauth_tests.rb +202 -0
- data/test/koala/facebook_with_access_token_tests.rb +41 -5
- data/test/koala_tests.rb +5 -1
- metadata +7 -6
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
v0.5.0
|
2
|
+
-- Added several new OAuth methods for making and parsing access token requests
|
3
|
+
-- Added test suite for the OAuth class
|
4
|
+
-- Made second argument to url_for_access_token a hash (strings still work but trigger a deprecation warning)
|
5
|
+
-- Added fields to facebook_data.yml
|
6
|
+
-- Updated readme
|
7
|
+
|
1
8
|
v0.4.1
|
2
9
|
-- Encapsulated GraphAPI and OAuth classes in the Koala::Facebook module for clarity (and to avoid claiming the global Facebook class)
|
3
10
|
-- Moved make_request method to Koala class from GraphAPI instance (for use by future OAuth class functionality)
|
data/Manifest
CHANGED
@@ -2,11 +2,11 @@ CHANGELOG
|
|
2
2
|
Manifest
|
3
3
|
Rakefile
|
4
4
|
init.rb
|
5
|
-
koala.gemspec
|
6
5
|
lib/http_services.rb
|
7
6
|
lib/koala.rb
|
8
7
|
readme.md
|
9
8
|
test/facebook_data.yml
|
10
9
|
test/koala/facebook_no_access_token_tests.rb
|
10
|
+
test/koala/facebook_oauth_tests.rb
|
11
11
|
test/koala/facebook_with_access_token_tests.rb
|
12
12
|
test/koala_tests.rb
|
data/Rakefile
CHANGED
@@ -4,10 +4,10 @@ require 'rake'
|
|
4
4
|
require 'echoe'
|
5
5
|
|
6
6
|
# gem management
|
7
|
-
Echoe.new('koala', '0.
|
7
|
+
Echoe.new('koala', '0.5.0') do |p|
|
8
8
|
p.summary = "A lightweight, flexible library for Facebook's new Graph API"
|
9
9
|
p.description = "Koala is a lightweight, flexible Ruby SDK for Facebook's new Graph API. It allows read/write access to the Facebook Graph and provides OAuth URLs and cookie validation for Facebook Connect sites. Koala supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services."
|
10
|
-
p.url = "http://github.com/arsduo/
|
10
|
+
p.url = "http://github.com/arsduo/koala"
|
11
11
|
p.author = ["Alex Koppel", "Rafi Jacoby", "Context Optional"]
|
12
12
|
p.email = "alex@alexkoppel.com"
|
13
13
|
p.ignore_pattern = ["tmp/*", "script/*", "pkg/*"]
|
data/init.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# init.rb
|
2
|
-
require '
|
2
|
+
require 'koala'
|
data/koala.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{koala}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.5.0"
|
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, Rafi Jacoby, Context Optional"]
|
9
|
-
s.date = %q{2010-05-
|
9
|
+
s.date = %q{2010-05-08}
|
10
10
|
s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook's new Graph API. It allows read/write access to the Facebook Graph and provides OAuth URLs and cookie validation for Facebook Connect sites. Koala 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
12
|
s.extra_rdoc_files = ["CHANGELOG", "lib/http_services.rb", "lib/koala.rb"]
|
13
|
-
s.files = ["CHANGELOG", "Manifest", "Rakefile", "init.rb", "
|
14
|
-
s.homepage = %q{http://github.com/arsduo/
|
13
|
+
s.files = ["CHANGELOG", "Manifest", "Rakefile", "init.rb", "lib/http_services.rb", "lib/koala.rb", "readme.md", "test/facebook_data.yml", "test/koala/facebook_no_access_token_tests.rb", "test/koala/facebook_oauth_tests.rb", "test/koala/facebook_with_access_token_tests.rb", "test/koala_tests.rb", "koala.gemspec"]
|
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"]
|
17
17
|
s.rubyforge_project = %q{koala}
|
data/lib/http_services.rb
CHANGED
@@ -46,7 +46,7 @@ module Koala
|
|
46
46
|
base.class_eval do
|
47
47
|
require 'typhoeus' unless defined?(Typhoeus)
|
48
48
|
include Typhoeus
|
49
|
-
|
49
|
+
|
50
50
|
def self.make_request(path, args, verb)
|
51
51
|
# if the verb isn't get or post, send it as a post argument
|
52
52
|
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
data/lib/koala.rb
CHANGED
@@ -106,7 +106,7 @@ module Koala
|
|
106
106
|
# http://developers.facebook.com/docs/authentication/ for details about
|
107
107
|
# extended permissions.
|
108
108
|
|
109
|
-
raise GraphAPIError.new(
|
109
|
+
raise GraphAPIError.new({"type" => "KoalaMissingAccessToken", "message" => "Write operations require an access token"}) unless @access_token
|
110
110
|
api("#{parent_object}/#{connection_name}", args, "post")
|
111
111
|
end
|
112
112
|
|
@@ -161,8 +161,8 @@ module Koala
|
|
161
161
|
response = JSON.parse("[#{result}]")[0]
|
162
162
|
|
163
163
|
# check for errors
|
164
|
-
if response.is_a?(Hash) &&
|
165
|
-
raise GraphAPIError.new(
|
164
|
+
if response.is_a?(Hash) && error_details = response["error"]
|
165
|
+
raise GraphAPIError.new(error_details)
|
166
166
|
end
|
167
167
|
|
168
168
|
response
|
@@ -170,14 +170,15 @@ module Koala
|
|
170
170
|
end
|
171
171
|
|
172
172
|
class GraphAPIError < Exception
|
173
|
-
attr_accessor :
|
174
|
-
def initialize(
|
175
|
-
|
176
|
-
|
173
|
+
attr_accessor :fb_error_type
|
174
|
+
def initialize(details = {})
|
175
|
+
self.fb_error_type = details["type"]
|
176
|
+
super("#{fb_error_type}: #{details["message"]}")
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
-
class OAuth
|
180
|
+
class OAuth
|
181
|
+
attr_accessor :app_id, :app_secret, :oauth_callback_url
|
181
182
|
def initialize(app_id, app_secret, oauth_callback_url = nil)
|
182
183
|
@app_id = app_id
|
183
184
|
@app_secret = app_secret
|
@@ -207,12 +208,13 @@ module Koala
|
|
207
208
|
components = {}
|
208
209
|
fb_cookie.split("&").map {|param| param = param.split("="); components[param[0]] = param[1]}
|
209
210
|
|
211
|
+
# generate the signature and make sure it matches what we expect
|
210
212
|
auth_string = components.keys.sort.collect {|a| a == "sig" ? nil : "#{a}=#{components[a]}"}.reject {|a| a.nil?}.join("")
|
211
|
-
sig = Digest::MD5.hexdigest(auth_string + @app_secret)
|
212
|
-
|
213
|
-
sig == components["sig"] && (components["expires"].to_i == 0 || Time.now.to_i < components["expires"].to_i) ? components : nil
|
213
|
+
sig = Digest::MD5.hexdigest(auth_string + @app_secret)
|
214
|
+
sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
|
214
215
|
end
|
215
216
|
end
|
217
|
+
alias_method :get_user_from_cookies, :get_user_from_cookie
|
216
218
|
|
217
219
|
def url_for_oauth_code(options = {})
|
218
220
|
# for permissions, see http://developers.facebook.com/docs/authentication/permissions
|
@@ -220,15 +222,48 @@ module Koala
|
|
220
222
|
scope = permissions ? "&scope=#{permissions.is_a?(Array) ? permissions.join(",") : permissions}" : ""
|
221
223
|
|
222
224
|
callback = options[:callback] || @oauth_callback_url
|
225
|
+
raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback
|
223
226
|
|
224
227
|
# Creates the URL for oauth authorization for a given callback and optional set of permissions
|
225
228
|
"https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}"
|
226
229
|
end
|
227
230
|
|
228
|
-
def url_for_access_token(code,
|
231
|
+
def url_for_access_token(code, options = {})
|
229
232
|
# Creates the URL for the token corresponding to a given code generated by Facebook
|
233
|
+
if options.is_a?(String) # changing the arguments
|
234
|
+
puts "Deprecation warning: url_for_access_token now takes an options hash as the second argument; pass the callback as :callback."
|
235
|
+
options = {:callback => options}
|
236
|
+
end
|
237
|
+
callback = options[:callback] || @oauth_callback_url
|
238
|
+
raise ArgumentError, "url_for_access_token must get a callback either from the OAuth object or in the parameters!" unless callback
|
230
239
|
"https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
|
231
240
|
end
|
241
|
+
|
242
|
+
def parse_access_token(response_text)
|
243
|
+
components = response_text.split("&").inject({}) do |hash, bit|
|
244
|
+
key, value = bit.split("=")
|
245
|
+
hash.merge!(key => value)
|
246
|
+
end
|
247
|
+
components
|
248
|
+
end
|
249
|
+
|
250
|
+
def fetch_token_string(code)
|
251
|
+
Koala.make_request("oauth/access_token", {
|
252
|
+
:client_id => @app_id,
|
253
|
+
:redirect_uri => @oauth_callback_url,
|
254
|
+
:client_secret => @app_secret,
|
255
|
+
:code => code
|
256
|
+
}, "get")
|
257
|
+
end
|
258
|
+
|
259
|
+
def get_access_token(code)
|
260
|
+
result = fetch_token_string(code)
|
261
|
+
|
262
|
+
# if we have an error, parse the error JSON and raise an error
|
263
|
+
raise GraphAPIError.new((JSON.parse(result)["error"] rescue nil) || {}) if result =~ /error/
|
264
|
+
# otherwise, parse the access token
|
265
|
+
parse_access_token(result)
|
266
|
+
end
|
232
267
|
end
|
233
268
|
end
|
234
269
|
|
data/readme.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Koala
|
2
2
|
====
|
3
|
-
Koala (<a href="http://github.com/arsduo/
|
3
|
+
Koala (<a href="http://github.com/arsduo/koala" target="_blank">http://github.com/arsduo/koala</a>) is a new Facebook Graph library for Ruby. We wrote Koala with four goals:
|
4
4
|
|
5
5
|
* Lightweight: Koala should be as light and simple as Facebook’s own new libraries, providing API accessors and returning simple JSON. (We clock in, with comments, just over 300 lines of code.)
|
6
6
|
* Fast: Koala should, out of the box, be quick. In addition to supporting the vanilla Ruby networking libraries, it natively supports Typhoeus, our preferred gem for making fast HTTP requests. Of course, That brings us to our next topic:
|
@@ -20,7 +20,9 @@ to parse the cookies set by the JavaScript SDK for logged in users.
|
|
20
20
|
|
21
21
|
Examples and More Details
|
22
22
|
-----
|
23
|
-
There's a very detailed description and walkthrough of Koala at http://blog.twoalex.com/2010/05/03/introducing-koala-a-new-gem-for-facebooks-new-graph-api
|
23
|
+
There's a very detailed description and walkthrough of Koala at <a href="http://blog.twoalex.com/2010/05/03/introducing-koala-a-new-gem-for-facebooks-new-graph-api/">http://blog.twoalex.com/2010/05/03/introducing-koala-a-new-gem-for-facebooks-new-graph-api/</a>.
|
24
|
+
|
25
|
+
You can easily generate OAuth access tokens and any other data needed to play with the Graph API or OAuth at the Koala-powered <a href="http://oauth.twoalex.com" target="_blank">OAuth Playground</a>.
|
24
26
|
|
25
27
|
|
26
28
|
Testing
|
data/test/facebook_data.yml
CHANGED
@@ -1,9 +1,28 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
|
1
|
+
# Check out http://oauth.twoalex.com to easily generate tokens, cookies, etc.
|
2
|
+
# Those values will work with the default settings in this yaml.
|
3
|
+
# Of course, you can change this to work with your own app.
|
4
|
+
# Just remember to update all fields!
|
4
5
|
|
5
|
-
# for testing the
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
# for testing the GraphAPI class
|
7
|
+
# OAuth token should have publish_stream and read_stream permissions
|
8
|
+
oauth_token: 119908831367602|2.8VK0rWWLe3y4L8JfrpBupA__.3600.1273370400-2905623|u-QAARJz9UeZrF6ef2qu-Fk4UH0.
|
9
|
+
|
10
|
+
# for testing the OAuth class
|
11
|
+
# baseline app
|
12
|
+
oauth_test_data:
|
13
|
+
# You must supply these values yourself, since they will expire.
|
14
|
+
valid_cookies: # note: the tests stub the time class so these default cookies are always valid
|
15
|
+
fbs_119908831367602: '"access_token=119908831367602|2.LKE7ksSPOx0V_8mHPr2NHQ__.3600.1273363200-2905623|CMpi0AYbn03Oukzv94AUha2qbO4.&expires=1273363200&secret=lT_9zm5r5IbJ6Aa5O54nFw__&session_key=2.LKE7ksSPOx0V_8mHPr2NHQ__.3600.1273363200-2905623&sig=9515e93113921f9476a4efbdd4a3c746&uid=2905623"'
|
16
|
+
code: 2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|vdiZmnxKxh4WVSnxBxoEvcBfamU.
|
17
|
+
|
18
|
+
# These values will work out of the box
|
19
|
+
app_id: 119908831367602
|
20
|
+
secret: e45e55a333eec232d4206d2703de1307
|
21
|
+
callback_url: http://oauth.twoalex.com/
|
22
|
+
raw_token_string: "access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.&expires=6621"
|
23
|
+
raw_offline_access_token_string: access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.
|
24
|
+
expired_cookies:
|
25
|
+
fbs_119908831367602: '"access_token=119908831367602|2.xv9mi6QSOpr474s4n2X_pw__.3600.1273287600-2905623|yVt5WH_S6J5p3gFa5_5lBzckhws.&expires=1273287600&secret=V_E79ovQnXqxGctFuC_n5A__&session_key=2.xv9mi6QSOpr474s4n2X_pw__.3600.1273287600-2905623&sig=eeef60838c0c800258d89b7e6ddddddb&uid=2905623"'
|
26
|
+
offline_access_cookies:
|
27
|
+
# note: I've revoked the offline access for security reasons, so you can't make calls against this :)
|
28
|
+
fbs_119908831367602: '"access_token=119908831367602|08170230801eb225068e7a70-2905623|Q3LDCYYF8CX9cstxnZLsxiR0nwg.&expires=0&secret=78abaee300b392e275072a9f2727d436&session_key=08170230801eb225068e7a70-2905623&sig=423b8aa4b6fa1f9a571955f8e929d567&uid=2905623"'
|
@@ -0,0 +1,202 @@
|
|
1
|
+
# stub the Time class to always return a time for which the valid cookie is still valid
|
2
|
+
class Time
|
3
|
+
def self.now
|
4
|
+
self
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.to_i
|
8
|
+
1273363199
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class FacebookOAuthTests < Test::Unit::TestCase
|
13
|
+
describe "Koala GraphAPI without an access token" do
|
14
|
+
before :each do
|
15
|
+
# make the relevant test data easily accessible
|
16
|
+
@oauth_data = $testing_data["oauth_test_data"]
|
17
|
+
@app_id = @oauth_data["app_id"]
|
18
|
+
@secret = @oauth_data["secret"]
|
19
|
+
@code = @oauth_data["code"]
|
20
|
+
@callback_url = @oauth_data["callback_url"]
|
21
|
+
@raw_token_string = @oauth_data["raw_token_string"]
|
22
|
+
@raw_offline_access_token_string = @oauth_data["raw_offline_access_token_string"]
|
23
|
+
|
24
|
+
# this should expanded to cover all variables
|
25
|
+
raise Exception, "Must supply app data to run FacebookOAuthTests!" unless @app_id && @secret && @callback_url &&
|
26
|
+
@code && @raw_token_string &&
|
27
|
+
@raw_offline_access_token_string
|
28
|
+
|
29
|
+
@oauth = Koala::Facebook::OAuth.new(@app_id, @secret, @callback_url)
|
30
|
+
end
|
31
|
+
|
32
|
+
# initialization
|
33
|
+
it "should properly initialize" do
|
34
|
+
@oauth.should
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should properly set attributes" do
|
38
|
+
(@oauth.app_id == @app_id &&
|
39
|
+
@oauth.app_secret == @secret &&
|
40
|
+
@oauth.oauth_callback_url == @callback_url).should be_true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should properly initialize without a callback_url" do
|
44
|
+
@oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should properly set attributes without a callback URL" do
|
48
|
+
@oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
|
49
|
+
(@oauth.app_id == @app_id &&
|
50
|
+
@oauth.app_secret == @secret &&
|
51
|
+
@oauth.oauth_callback_url == nil).should be_true
|
52
|
+
end
|
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
|
59
|
+
|
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
|
66
|
+
|
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
|
71
|
+
|
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
|
78
|
+
|
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
|
83
|
+
|
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
|
89
|
+
end
|
90
|
+
|
91
|
+
# OAuth URLs
|
92
|
+
|
93
|
+
# url_for_oauth_code
|
94
|
+
it "should generate a properly formatted OAuth code URL with the default values" do
|
95
|
+
url = @oauth.url_for_oauth_code
|
96
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should generate a properly formatted OAuth code URL when a callback is given" do
|
100
|
+
callback = "foo.com"
|
101
|
+
url = @oauth.url_for_oauth_code(:callback => callback)
|
102
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}"
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
|
106
|
+
permissions = "publish_stream,read_stream"
|
107
|
+
url = @oauth.url_for_oauth_code(:permissions => permissions)
|
108
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions}"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
|
112
|
+
permissions = ["publish_stream", "read_stream"]
|
113
|
+
url = @oauth.url_for_oauth_code(:permissions => permissions)
|
114
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions.join(",")}"
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should generate a properly formatted OAuth code URL when both permissions and callback are provided" do
|
118
|
+
permissions = "publish_stream,read_stream"
|
119
|
+
callback = "foo.com"
|
120
|
+
url = @oauth.url_for_oauth_code(:callback => callback, :permissions => permissions)
|
121
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}&scope=#{permissions}"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should raise an exception if no callback is given in initialization or the call" do
|
125
|
+
oauth2 = Koala::Facebook::OAuth.new(@app_id, @secret)
|
126
|
+
begin
|
127
|
+
url = oauth2.url_for_oauth_code
|
128
|
+
rescue ArgumentError => @right_err
|
129
|
+
rescue
|
130
|
+
end
|
131
|
+
|
132
|
+
@right_err.should
|
133
|
+
end
|
134
|
+
|
135
|
+
# url_for_access_token
|
136
|
+
it "should generate a properly formatted OAuth token URL when provided a code" do
|
137
|
+
url = @oauth.url_for_access_token(@code)
|
138
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{@callback_url}&client_secret=#{@secret}&code=#{@code}"
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should generate a properly formatted OAuth token URL when provided a callback" do
|
142
|
+
callback = "foo.com"
|
143
|
+
url = @oauth.url_for_access_token(@code, :callback => callback)
|
144
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@secret}&code=#{@code}"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should output a deprecation warning but generate a properly formatted OAuth token URL when provided a callback in the deprecated fashion" do
|
148
|
+
callback = "foo.com"
|
149
|
+
url = out = nil
|
150
|
+
|
151
|
+
begin
|
152
|
+
# we want to capture the deprecation warning as well as the output
|
153
|
+
# credit to http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/ for the technique
|
154
|
+
out = StringIO.new
|
155
|
+
$stdout = out
|
156
|
+
url = @oauth.url_for_access_token(@code, callback)
|
157
|
+
ensure
|
158
|
+
$stdout = STDOUT
|
159
|
+
end
|
160
|
+
|
161
|
+
# two assertions may be bad test writing, but this is for a deprecated method
|
162
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@secret}&code=#{@code}"
|
163
|
+
out.should_not be_nil
|
164
|
+
end
|
165
|
+
|
166
|
+
# parse_access_token
|
167
|
+
it "should properly parse access token results" do
|
168
|
+
result = @oauth.parse_access_token(@raw_token_string)
|
169
|
+
has_both_parts = result["access_token"] && result["expires"]
|
170
|
+
has_both_parts.should
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should properly parse offline access token results" do
|
174
|
+
result = @oauth.parse_access_token(@raw_offline_access_token_string)
|
175
|
+
has_both_parts = result["access_token"] && !result["expires"]
|
176
|
+
has_both_parts.should
|
177
|
+
end
|
178
|
+
|
179
|
+
# fetch_token_string
|
180
|
+
# note -- we just test that this looks right, since get_access_token tests the parsing too
|
181
|
+
it "should fetch a proper token string from Facebook when given a code" do
|
182
|
+
result = @oauth.fetch_token_string(@code)
|
183
|
+
result.should =~ /^access_token/
|
184
|
+
end
|
185
|
+
|
186
|
+
# get_access_token
|
187
|
+
it "should properly get and parse an access token token results" do
|
188
|
+
result = @oauth.get_access_token(@code)
|
189
|
+
result["access_token"].should
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should raise an error when get_access_token is called with a bad code" do
|
193
|
+
begin
|
194
|
+
result = @oauth.get_access_token("foo")
|
195
|
+
rescue Koala::Facebook::GraphAPIError => @right_err
|
196
|
+
rescue
|
197
|
+
end
|
198
|
+
@right_err.should
|
199
|
+
end
|
200
|
+
end # describe
|
201
|
+
|
202
|
+
end #class
|
@@ -10,7 +10,8 @@ class FacebookWithAccessTokenTests < Test::Unit::TestCase
|
|
10
10
|
# clean up any temporary objects
|
11
11
|
if @temporary_object_id
|
12
12
|
puts "\nCleaning up temporary object #{@temporary_object_id.to_s}"
|
13
|
-
@graph.delete_object(@temporary_object_id)
|
13
|
+
result = @graph.delete_object(@temporary_object_id)
|
14
|
+
raise "Unable to clean up temporary Graph object #{@temporary_object_id}!" unless result
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -53,26 +54,47 @@ class FacebookWithAccessTokenTests < Test::Unit::TestCase
|
|
53
54
|
end
|
54
55
|
|
55
56
|
# PUT
|
56
|
-
it "should be able to
|
57
|
+
it "should be able to write an object to the graph" do
|
57
58
|
result = @graph.put_wall_post("Hello, world, from the test suite!")
|
58
59
|
@temporary_object_id = result["id"]
|
59
60
|
@temporary_object_id.should_not be_nil
|
60
61
|
end
|
61
62
|
|
62
63
|
# DELETE
|
63
|
-
it "should
|
64
|
+
it "should be able to delete posts" do
|
64
65
|
result = @graph.put_wall_post("Hello, world, from the test suite delete method!")
|
65
66
|
object_id_to_delete = result["id"]
|
66
67
|
delete_result = @graph.delete_object(object_id_to_delete)
|
67
68
|
delete_result.should == true
|
68
69
|
end
|
69
70
|
|
70
|
-
#
|
71
|
-
it "should be able to
|
71
|
+
# additional put tests
|
72
|
+
it "should be able to verify messages posted to a wall" do
|
73
|
+
message = "the cats are asleep"
|
74
|
+
put_result = @graph.put_wall_post(message)
|
75
|
+
@temporary_object_id = put_result["id"]
|
76
|
+
get_result = @graph.get_object(@temporary_object_id)
|
77
|
+
|
78
|
+
# make sure the message we sent is the message that got posted
|
79
|
+
get_result["message"].should == message
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should be able to post a message with an attachment to a feed" do
|
72
83
|
result = @graph.put_wall_post("Hello, world, from the test suite again!", {:name => "Context Optional", :link => "http://www.contextoptional.com/"})
|
73
84
|
@temporary_object_id = result["id"]
|
74
85
|
@temporary_object_id.should_not be_nil
|
75
86
|
end
|
87
|
+
|
88
|
+
it "should be able to verify a message with an attachment posted to a feed" do
|
89
|
+
attachment = {"name" => "Context Optional", "link" => "http://www.contextoptional.com/"}
|
90
|
+
result = @graph.put_wall_post("Hello, world, from the test suite again!", attachment)
|
91
|
+
@temporary_object_id = result["id"]
|
92
|
+
get_result = @graph.get_object(@temporary_object_id)
|
93
|
+
|
94
|
+
# make sure the result we fetch includes all the parameters we sent
|
95
|
+
it_matches = attachment.inject(true) {|valid, param| valid && (get_result[param[0]] == attachment[param[0]])}
|
96
|
+
it_matches.should == true
|
97
|
+
end
|
76
98
|
|
77
99
|
it "should be able to comment on an object" do
|
78
100
|
result = @graph.put_wall_post("Hello, world, from the test suite, testing comments!")
|
@@ -82,6 +104,20 @@ class FacebookWithAccessTokenTests < Test::Unit::TestCase
|
|
82
104
|
comment_result = @graph.put_comment(@temporary_object_id, "it's my comment!")
|
83
105
|
comment_result.should_not be_nil
|
84
106
|
end
|
107
|
+
|
108
|
+
it "should be able to verify a comment posted about an object" do
|
109
|
+
message_text = "Hello, world, from the test suite, testing comments!"
|
110
|
+
result = @graph.put_wall_post(message_text)
|
111
|
+
@temporary_object_id = result["id"]
|
112
|
+
|
113
|
+
# this will be deleted when the post gets deleted
|
114
|
+
comment_text = "it's my comment!"
|
115
|
+
comment_result = @graph.put_comment(@temporary_object_id, comment_text)
|
116
|
+
get_result = @graph.get_object(comment_result["id"])
|
117
|
+
|
118
|
+
# make sure the text of the comment matches what we sent
|
119
|
+
get_result["message"].should == comment_text
|
120
|
+
end
|
85
121
|
|
86
122
|
it "should be able to like an object" do
|
87
123
|
result = @graph.put_wall_post("Hello, world, from the test suite, testing comments!")
|
data/test/koala_tests.rb
CHANGED
@@ -2,16 +2,20 @@ require 'test/unit'
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'spec/test/unit'
|
4
4
|
|
5
|
+
# load the libraries
|
5
6
|
require 'koala'
|
7
|
+
|
8
|
+
# load the tests
|
6
9
|
require 'koala/facebook_no_access_token_tests'
|
7
10
|
require 'koala/facebook_with_access_token_tests'
|
11
|
+
require 'koala/facebook_oauth_tests'
|
8
12
|
|
9
13
|
class FacebookTestSuite
|
10
14
|
def self.suite
|
11
15
|
suite = Test::Unit::TestSuite.new
|
12
16
|
suite << FacebookNoAccessTokenTests.suite
|
13
17
|
suite << FacebookWithAccessTokenTests.suite
|
14
|
-
|
18
|
+
suite << FacebookOAuthTests.suite
|
15
19
|
suite
|
16
20
|
end
|
17
21
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 5
|
8
|
+
- 0
|
9
|
+
version: 0.5.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alex Koppel, Rafi Jacoby, Context Optional
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-08 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -33,16 +33,17 @@ files:
|
|
33
33
|
- Manifest
|
34
34
|
- Rakefile
|
35
35
|
- init.rb
|
36
|
-
- koala.gemspec
|
37
36
|
- lib/http_services.rb
|
38
37
|
- lib/koala.rb
|
39
38
|
- readme.md
|
40
39
|
- test/facebook_data.yml
|
41
40
|
- test/koala/facebook_no_access_token_tests.rb
|
41
|
+
- test/koala/facebook_oauth_tests.rb
|
42
42
|
- test/koala/facebook_with_access_token_tests.rb
|
43
43
|
- test/koala_tests.rb
|
44
|
+
- koala.gemspec
|
44
45
|
has_rdoc: true
|
45
|
-
homepage: http://github.com/arsduo/
|
46
|
+
homepage: http://github.com/arsduo/koala
|
46
47
|
licenses: []
|
47
48
|
|
48
49
|
post_install_message:
|