joelind-koala 0.8.1
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.
- data/CHANGELOG +88 -0
- data/LICENSE +22 -0
- data/Manifest +29 -0
- data/Rakefile +17 -0
- data/init.rb +2 -0
- data/joelind-koala.gemspec +30 -0
- data/koala.gemspec +30 -0
- data/lib/koala/graph_api.rb +131 -0
- data/lib/koala/http_services.rb +70 -0
- data/lib/koala/realtime_updates.rb +95 -0
- data/lib/koala/rest_api.rb +23 -0
- data/lib/koala.rb +292 -0
- data/readme.md +104 -0
- data/spec/facebook_data.yml +44 -0
- data/spec/koala/api_base_tests.rb +80 -0
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +10 -0
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +11 -0
- data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +105 -0
- data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +139 -0
- data/spec/koala/live_testing_data_helper.rb +15 -0
- data/spec/koala/net_http_service_tests.rb +181 -0
- data/spec/koala/oauth/oauth_tests.rb +308 -0
- data/spec/koala/realtime_updates/realtime_updates_tests.rb +187 -0
- data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +94 -0
- data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +36 -0
- data/spec/koala_spec.rb +18 -0
- data/spec/koala_spec_helper.rb +30 -0
- data/spec/koala_spec_without_mocks.rb +19 -0
- data/spec/mock_facebook_responses.yml +228 -0
- data/spec/mock_http_service.rb +81 -0
- metadata +103 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
shared_examples_for "Koala GraphAPI with an access token" do
|
2
|
+
it "should get public data about a user" do
|
3
|
+
result = @api.get_object("koppel")
|
4
|
+
# the results should have an ID and a name, among other things
|
5
|
+
(result["id"] && result["name"]).should_not be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should get private data about a user" do
|
9
|
+
result = @api.get_object("koppel")
|
10
|
+
# updated_time should be a pretty fixed test case
|
11
|
+
result["updated_time"].should_not be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should get public data about a Page" do
|
15
|
+
result = @api.get_object("contextoptional")
|
16
|
+
# the results should have an ID and a name, among other things
|
17
|
+
(result["id"] && result["name"]).should
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should get data about 'me'" do
|
21
|
+
result = @api.get_object("me")
|
22
|
+
result["updated_time"].should
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be able to get multiple objects" do
|
26
|
+
result = @api.get_objects(["contextoptional", "naitik"])
|
27
|
+
result.length.should == 2
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be able to access a user's picture" do
|
31
|
+
@api.get_picture("chris.baclig").should =~ /http\:\/\//
|
32
|
+
end
|
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
|
+
|
38
|
+
it "should be able to access connections from users" do
|
39
|
+
result = @api.get_connections("lukeshepard", "likes")
|
40
|
+
result.length.should > 0
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be able to access connections from public Pages" do
|
44
|
+
result = @api.get_connections("contextoptional", "likes")
|
45
|
+
result.should be_a(Array)
|
46
|
+
end
|
47
|
+
|
48
|
+
# PUT
|
49
|
+
it "should be able to write an object to the graph" do
|
50
|
+
result = @api.put_wall_post("Hello, world, from the test suite!")
|
51
|
+
@temporary_object_id = result["id"]
|
52
|
+
@temporary_object_id.should_not be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
# DELETE
|
56
|
+
it "should be able to delete posts" do
|
57
|
+
result = @api.put_wall_post("Hello, world, from the test suite delete method!")
|
58
|
+
object_id_to_delete = result["id"]
|
59
|
+
delete_result = @api.delete_object(object_id_to_delete)
|
60
|
+
delete_result.should == true
|
61
|
+
end
|
62
|
+
|
63
|
+
# additional put tests
|
64
|
+
it "should be able to verify messages posted to a wall" do
|
65
|
+
message = "the cats are asleep"
|
66
|
+
put_result = @api.put_wall_post(message)
|
67
|
+
@temporary_object_id = put_result["id"]
|
68
|
+
get_result = @api.get_object(@temporary_object_id)
|
69
|
+
|
70
|
+
# make sure the message we sent is the message that got posted
|
71
|
+
get_result["message"].should == message
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be able to post a message with an attachment to a feed" do
|
75
|
+
result = @api.put_wall_post("Hello, world, from the test suite again!", {:name => "Context Optional", :link => "http://www.contextoptional.com/"})
|
76
|
+
@temporary_object_id = result["id"]
|
77
|
+
@temporary_object_id.should_not be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should be able to verify a message with an attachment posted to a feed" do
|
81
|
+
attachment = {"name" => "Context Optional", "link" => "http://www.contextoptional.com/"}
|
82
|
+
result = @api.put_wall_post("Hello, world, from the test suite again!", attachment)
|
83
|
+
@temporary_object_id = result["id"]
|
84
|
+
get_result = @api.get_object(@temporary_object_id)
|
85
|
+
|
86
|
+
# make sure the result we fetch includes all the parameters we sent
|
87
|
+
it_matches = attachment.inject(true) {|valid, param| valid && (get_result[param[0]] == attachment[param[0]])}
|
88
|
+
it_matches.should == true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should be able to comment on an object" do
|
92
|
+
result = @api.put_wall_post("Hello, world, from the test suite, testing comments!")
|
93
|
+
@temporary_object_id = result["id"]
|
94
|
+
|
95
|
+
# this will be deleted when the post gets deleted
|
96
|
+
comment_result = @api.put_comment(@temporary_object_id, "it's my comment!")
|
97
|
+
comment_result.should_not be_nil
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should be able to verify a comment posted about an object" do
|
101
|
+
message_text = "Hello, world, from the test suite, testing comments!"
|
102
|
+
result = @api.put_wall_post(message_text)
|
103
|
+
@temporary_object_id = result["id"]
|
104
|
+
|
105
|
+
# this will be deleted when the post gets deleted
|
106
|
+
comment_text = "it's my comment!"
|
107
|
+
comment_result = @api.put_comment(@temporary_object_id, comment_text)
|
108
|
+
get_result = @api.get_object(comment_result["id"])
|
109
|
+
|
110
|
+
# make sure the text of the comment matches what we sent
|
111
|
+
get_result["message"].should == comment_text
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should be able to like an object" do
|
115
|
+
result = @api.put_wall_post("Hello, world, from the test suite, testing comments!")
|
116
|
+
@temporary_object_id = result["id"]
|
117
|
+
like_result = @api.put_like(@temporary_object_id)
|
118
|
+
end
|
119
|
+
|
120
|
+
# SEARCH
|
121
|
+
it "should be able to search" do
|
122
|
+
result = @api.search("facebook")
|
123
|
+
result["data"].should be_an(Array)
|
124
|
+
end
|
125
|
+
|
126
|
+
# API
|
127
|
+
# the above tests test this already, but we should consider additional api tests
|
128
|
+
end
|
129
|
+
|
130
|
+
class FacebookWithAccessTokenTests < Test::Unit::TestCase
|
131
|
+
describe "Koala GraphAPI with an access token" do
|
132
|
+
it_should_behave_like "live testing examples"
|
133
|
+
it_should_behave_like "Koala GraphAPI with an access token"
|
134
|
+
|
135
|
+
before :each do
|
136
|
+
@api = Koala::Facebook::GraphAPI.new(@token)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
shared_examples_for "live testing examples" do
|
2
|
+
before :each do
|
3
|
+
@token = $testing_data["oauth_token"]
|
4
|
+
raise Exception, "Must supply access token to run FacebookWithAccessTokenTests!" unless @token
|
5
|
+
end
|
6
|
+
|
7
|
+
after :each do
|
8
|
+
# clean up any temporary objects
|
9
|
+
if @temporary_object_id
|
10
|
+
puts "\nCleaning up temporary object #{@temporary_object_id.to_s}"
|
11
|
+
result = @api.delete_object(@temporary_object_id)
|
12
|
+
raise "Unable to clean up temporary Graph object #{@temporary_object_id}!" unless result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'koala/http_services'
|
2
|
+
|
3
|
+
class NetHTTPServiceTests < Test::Unit::TestCase
|
4
|
+
module Bear
|
5
|
+
include Koala::NetHTTPService
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should define a make_request static module method" do
|
9
|
+
Bear.respond_to?(:make_request).should be_true
|
10
|
+
end
|
11
|
+
|
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
|
136
|
+
|
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
|
181
|
+
end
|
@@ -0,0 +1,308 @@
|
|
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
|
+
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
|
60
|
+
|
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
|
67
|
+
|
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
|
72
|
+
|
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
|
79
|
+
|
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
|
84
|
+
|
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 if the cookies are valid" do
|
101
|
+
result = @oauth.get_user_from_cookies(@oauth_data["valid_cookies"])
|
102
|
+
result.should be_a(String)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should return nil if the cookies are invalid" do
|
106
|
+
# make an invalid string by replacing some values
|
107
|
+
bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
|
108
|
+
result = @oauth.get_user_from_cookies(bad_cookie_hash)
|
109
|
+
result.should be_nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# OAuth URLs
|
115
|
+
|
116
|
+
# url_for_oauth_code
|
117
|
+
it "should generate a properly formatted OAuth code URL with the default values" do
|
118
|
+
url = @oauth.url_for_oauth_code
|
119
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}"
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should generate a properly formatted OAuth code URL when a callback is given" do
|
123
|
+
callback = "foo.com"
|
124
|
+
url = @oauth.url_for_oauth_code(:callback => callback)
|
125
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
|
129
|
+
permissions = "publish_stream,read_stream"
|
130
|
+
url = @oauth.url_for_oauth_code(:permissions => permissions)
|
131
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions}"
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
|
135
|
+
permissions = ["publish_stream", "read_stream"]
|
136
|
+
url = @oauth.url_for_oauth_code(:permissions => permissions)
|
137
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions.join(",")}"
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should generate a properly formatted OAuth code URL when both permissions and callback are provided" do
|
141
|
+
permissions = "publish_stream,read_stream"
|
142
|
+
callback = "foo.com"
|
143
|
+
url = @oauth.url_for_oauth_code(:callback => callback, :permissions => permissions)
|
144
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}&scope=#{permissions}"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should raise an exception if no callback is given in initialization or the call" do
|
148
|
+
oauth2 = Koala::Facebook::OAuth.new(@app_id, @secret)
|
149
|
+
lambda { oauth2.url_for_oauth_code }.should raise_error(ArgumentError)
|
150
|
+
end
|
151
|
+
|
152
|
+
# url_for_access_token
|
153
|
+
it "should generate a properly formatted OAuth token URL when provided a code" do
|
154
|
+
url = @oauth.url_for_access_token(@code)
|
155
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{@callback_url}&client_secret=#{@secret}&code=#{@code}"
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should generate a properly formatted OAuth token URL when provided a callback" do
|
159
|
+
callback = "foo.com"
|
160
|
+
url = @oauth.url_for_access_token(@code, :callback => callback)
|
161
|
+
url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@secret}&code=#{@code}"
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "get_access_token_info" do
|
165
|
+
it "should properly get and parse an access token token results into a hash" do
|
166
|
+
result = @oauth.get_access_token_info(@code)
|
167
|
+
result.should be_a(Hash)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should properly include the access token results" do
|
171
|
+
result = @oauth.get_access_token_info(@code)
|
172
|
+
result["access_token"].should
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should raise an error when get_access_token is called with a bad code" do
|
176
|
+
lambda { @oauth.get_access_token_info("foo") }.should raise_error(Koala::Facebook::APIError)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "get_access_token" do
|
181
|
+
it "should use get_access_token_info to get and parse an access token token results" do
|
182
|
+
result = @oauth.get_access_token(@code)
|
183
|
+
result.should be_a(String)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should return the access token as a string" do
|
187
|
+
result = @oauth.get_access_token(@code)
|
188
|
+
original = @oauth.get_access_token_info(@code)
|
189
|
+
result.should == original["access_token"]
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should raise an error when get_access_token is called with a bad code" do
|
193
|
+
lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::APIError)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "get_app_access_token_info" do
|
198
|
+
it "should properly get and parse an app's access token as a hash" do
|
199
|
+
result = @oauth.get_app_access_token_info
|
200
|
+
result.should be_a(Hash)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should include the access token" do
|
204
|
+
result = @oauth.get_app_access_token_info
|
205
|
+
result["access_token"].should
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "get_app_acess_token" do
|
210
|
+
it "should use get_access_token_info to get and parse an access token token results" do
|
211
|
+
result = @oauth.get_app_access_token
|
212
|
+
result.should be_a(String)
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should return the access token as a string" do
|
216
|
+
result = @oauth.get_app_access_token
|
217
|
+
original = @oauth.get_app_access_token_info
|
218
|
+
result.should == original["access_token"]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "exchanging session keys" do
|
223
|
+
describe "with get_token_info_from_session_keys" do
|
224
|
+
it "should get an array of session keys from Facebook when passed a single key" do
|
225
|
+
result = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
|
226
|
+
result.should be_an(Array)
|
227
|
+
result.length.should == 1
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should get an array of session keys from Facebook when passed multiple keys" do
|
231
|
+
result = @oauth.get_tokens_from_session_keys(@oauth_data["multiple_session_keys"])
|
232
|
+
result.should be_an(Array)
|
233
|
+
result.length.should == 2
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should return the original hashes" do
|
237
|
+
result = @oauth.get_token_info_from_session_keys(@oauth_data["multiple_session_keys"])
|
238
|
+
result[0].should be_a(Hash)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "with get_tokens_from_session_keys" do
|
243
|
+
it "should call get_token_info_from_session_keys" do
|
244
|
+
args = @oauth_data["multiple_session_keys"]
|
245
|
+
@oauth.should_receive(:get_token_info_from_session_keys).with(args).and_return([])
|
246
|
+
@oauth.get_tokens_from_session_keys(args)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should return an array of strings" do
|
250
|
+
args = @oauth_data["multiple_session_keys"]
|
251
|
+
result = @oauth.get_tokens_from_session_keys(args)
|
252
|
+
result.each {|r| r.should be_a(String) }
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe "get_token_from_session_key" do
|
257
|
+
it "should call get_tokens_from_session_keys when the get_token_from_session_key is called" do
|
258
|
+
key = @oauth_data["session_key"]
|
259
|
+
@oauth.should_receive(:get_tokens_from_session_keys).with([key]).and_return([])
|
260
|
+
@oauth.get_token_from_session_key(key)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should get back the access token string from get_token_from_session_key" do
|
264
|
+
result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
|
265
|
+
result.should be_a(String)
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should be the first value in the array" do
|
269
|
+
result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
|
270
|
+
array = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
|
271
|
+
result.should == array[0]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# protected methods
|
277
|
+
# since these are pretty fundamental and pretty testable, we want to test them
|
278
|
+
|
279
|
+
# parse_access_token
|
280
|
+
it "should properly parse access token results" do
|
281
|
+
result = @oauth.send(:parse_access_token, @raw_token_string)
|
282
|
+
has_both_parts = result["access_token"] && result["expires"]
|
283
|
+
has_both_parts.should
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should properly parse offline access token results" do
|
287
|
+
result = @oauth.send(:parse_access_token, @raw_offline_access_token_string)
|
288
|
+
has_both_parts = result["access_token"] && !result["expires"]
|
289
|
+
has_both_parts.should
|
290
|
+
end
|
291
|
+
|
292
|
+
# fetch_token_string
|
293
|
+
# somewhat duplicative with the tests for get_access_token and get_app_access_token
|
294
|
+
# but no harm in thoroughness
|
295
|
+
it "should fetch a proper token string from Facebook when given a code" do
|
296
|
+
result = @oauth.send(:fetch_token_string, :code => @code, :redirect_uri => @callback_url)
|
297
|
+
result.should =~ /^access_token/
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should fetch a proper token string from Facebook when asked for the app token" do
|
301
|
+
result = @oauth.send(:fetch_token_string, {:type => 'client_cred'}, true)
|
302
|
+
result.should =~ /^access_token/
|
303
|
+
end
|
304
|
+
|
305
|
+
# END CODE THAT NEEDS MOCKING
|
306
|
+
end # describe
|
307
|
+
|
308
|
+
end #class
|