koala 0.9.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +42 -7
  3. data/Gemfile +3 -0
  4. data/LICENSE +1 -1
  5. data/Manifest +10 -1
  6. data/Rakefile +13 -14
  7. data/koala.gemspec +36 -19
  8. data/lib/koala/graph_api.rb +188 -123
  9. data/lib/koala/http_services.rb +93 -18
  10. data/lib/koala/rest_api.rb +73 -6
  11. data/lib/koala/test_users.rb +85 -0
  12. data/lib/koala/uploadable_io.rb +115 -0
  13. data/lib/koala.rb +114 -116
  14. data/readme.md +32 -18
  15. data/spec/cases/api_base_spec.rb +101 -0
  16. data/spec/cases/graph_and_rest_api_spec.rb +31 -0
  17. data/spec/cases/graph_api_spec.rb +25 -0
  18. data/spec/cases/http_services/http_service_spec.rb +54 -0
  19. data/spec/cases/http_services/net_http_service_spec.rb +350 -0
  20. data/spec/cases/http_services/typhoeus_service_spec.rb +144 -0
  21. data/spec/cases/oauth_spec.rb +409 -0
  22. data/spec/cases/realtime_updates_spec.rb +184 -0
  23. data/spec/cases/rest_api_spec.rb +25 -0
  24. data/spec/cases/test_users_spec.rb +221 -0
  25. data/spec/cases/uploadable_io_spec.rb +151 -0
  26. data/spec/fixtures/beach.jpg +0 -0
  27. data/spec/{facebook_data.yml → fixtures/facebook_data.yml} +18 -14
  28. data/spec/{mock_facebook_responses.yml → fixtures/mock_facebook_responses.yml} +314 -241
  29. data/spec/spec_helper.rb +18 -0
  30. data/spec/support/graph_api_shared_examples.rb +424 -0
  31. data/spec/support/live_testing_data_helper.rb +40 -0
  32. data/spec/{mock_http_service.rb → support/mock_http_service.rb} +94 -80
  33. data/spec/support/rest_api_shared_examples.rb +161 -0
  34. data/spec/support/setup_mocks_or_live.rb +52 -0
  35. data/spec/support/uploadable_io_shared_examples.rb +76 -0
  36. metadata +131 -43
  37. data/init.rb +0 -2
  38. data/spec/koala/api_base_tests.rb +0 -96
  39. data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +0 -10
  40. data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +0 -11
  41. data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +0 -114
  42. data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +0 -150
  43. data/spec/koala/graph_api/graph_collection_tests.rb +0 -104
  44. data/spec/koala/live_testing_data_helper.rb +0 -23
  45. data/spec/koala/net_http_service_tests.rb +0 -186
  46. data/spec/koala/oauth/oauth_tests.rb +0 -433
  47. data/spec/koala/realtime_updates/realtime_updates_tests.rb +0 -187
  48. data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +0 -94
  49. data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +0 -36
  50. data/spec/koala_spec.rb +0 -18
  51. data/spec/koala_spec_helper.rb +0 -45
  52. data/spec/koala_spec_without_mocks.rb +0 -19
@@ -0,0 +1,409 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Koala::Facebook::OAuth" do
4
+ before :each do
5
+ # make the relevant test data easily accessible
6
+ @oauth_data = $testing_data["oauth_test_data"]
7
+ @app_id = @oauth_data["app_id"]
8
+ @secret = @oauth_data["secret"]
9
+ @code = @oauth_data["code"]
10
+ @callback_url = @oauth_data["callback_url"]
11
+ @raw_token_string = @oauth_data["raw_token_string"]
12
+ @raw_offline_access_token_string = @oauth_data["raw_offline_access_token_string"]
13
+
14
+ # for signed requests (http://developers.facebook.com/docs/authentication/canvas/encryption_proposal)
15
+ @signed_params = @oauth_data["signed_params"]
16
+ @signed_params_result = @oauth_data["signed_params_result"]
17
+
18
+ # this should expanded to cover all variables
19
+ raise Exception, "Must supply app data to run FacebookOAuthTests!" unless @app_id && @secret && @callback_url &&
20
+ @code && @raw_token_string &&
21
+ @raw_offline_access_token_string
22
+
23
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret, @callback_url)
24
+
25
+ @time = Time.now
26
+ Time.stub!(:now).and_return(@time)
27
+ @time.stub!(:to_i).and_return(1273363199)
28
+ end
29
+
30
+ # initialization
31
+ it "should properly initialize" do
32
+ @oauth.should
33
+ end
34
+
35
+ it "should properly set attributes" do
36
+ (@oauth.app_id == @app_id &&
37
+ @oauth.app_secret == @secret &&
38
+ @oauth.oauth_callback_url == @callback_url).should be_true
39
+ end
40
+
41
+ it "should properly initialize without a callback_url" do
42
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
43
+ end
44
+
45
+ it "should properly set attributes without a callback URL" do
46
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
47
+ (@oauth.app_id == @app_id &&
48
+ @oauth.app_secret == @secret &&
49
+ @oauth.oauth_callback_url == nil).should be_true
50
+ end
51
+
52
+ describe "for cookie parsing" do
53
+ describe "get_user_info_from_cookies" do
54
+ it "should properly parse valid cookies" do
55
+ result = @oauth.get_user_info_from_cookies(@oauth_data["valid_cookies"])
56
+ result.should be_a(Hash)
57
+ end
58
+
59
+ it "should return all the cookie components from valid cookie string" do
60
+ cookie_data = @oauth_data["valid_cookies"]
61
+ parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
62
+ number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
63
+ parsing_results.length.should == number_of_components
64
+ end
65
+
66
+ it "should properly parse valid offline access cookies (e.g. no expiration)" do
67
+ result = @oauth.get_user_info_from_cookies(@oauth_data["offline_access_cookies"])
68
+ result["uid"].should
69
+ end
70
+
71
+ it "should return all the cookie components from offline access cookies" do
72
+ cookie_data = @oauth_data["offline_access_cookies"]
73
+ parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
74
+ number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
75
+ parsing_results.length.should == number_of_components
76
+ end
77
+
78
+ it "shouldn't parse expired cookies" do
79
+ result = @oauth.get_user_info_from_cookies(@oauth_data["expired_cookies"])
80
+ result.should be_nil
81
+ end
82
+
83
+ it "shouldn't parse invalid cookies" do
84
+ # make an invalid string by replacing some values
85
+ bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
86
+ result = @oauth.get_user_info_from_cookies(bad_cookie_hash)
87
+ result.should be_nil
88
+ end
89
+ end
90
+
91
+ describe "get_user_from_cookies" do
92
+ it "should use get_user_info_from_cookies to parse the cookies" do
93
+ data = @oauth_data["valid_cookies"]
94
+ @oauth.should_receive(:get_user_info_from_cookies).with(data).and_return({})
95
+ @oauth.get_user_from_cookies(data)
96
+ end
97
+
98
+ it "should use return a string if the cookies are valid" do
99
+ result = @oauth.get_user_from_cookies(@oauth_data["valid_cookies"])
100
+ result.should be_a(String)
101
+ end
102
+
103
+ it "should return nil if the cookies are invalid" do
104
+ # make an invalid string by replacing some values
105
+ bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
106
+ result = @oauth.get_user_from_cookies(bad_cookie_hash)
107
+ result.should be_nil
108
+ end
109
+ end
110
+ end
111
+
112
+ # OAuth URLs
113
+
114
+ describe "for URL generation" do
115
+
116
+ describe "for OAuth codes" do
117
+ # url_for_oauth_code
118
+ it "should generate a properly formatted OAuth code URL with the default values" do
119
+ url = @oauth.url_for_oauth_code
120
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}"
121
+ end
122
+
123
+ it "should generate a properly formatted OAuth code URL when a callback is given" do
124
+ callback = "foo.com"
125
+ url = @oauth.url_for_oauth_code(:callback => callback)
126
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}"
127
+ end
128
+
129
+ it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
130
+ permissions = "publish_stream,read_stream"
131
+ url = @oauth.url_for_oauth_code(:permissions => permissions)
132
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions}"
133
+ end
134
+
135
+ it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
136
+ permissions = ["publish_stream", "read_stream"]
137
+ url = @oauth.url_for_oauth_code(:permissions => permissions)
138
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions.join(",")}"
139
+ end
140
+
141
+ it "should generate a properly formatted OAuth code URL when both permissions and callback are provided" do
142
+ permissions = "publish_stream,read_stream"
143
+ callback = "foo.com"
144
+ url = @oauth.url_for_oauth_code(:callback => callback, :permissions => permissions)
145
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}&scope=#{permissions}"
146
+ end
147
+
148
+ it "should generate a properly formatted OAuth code URL when a display is given as a string" do
149
+ url = @oauth.url_for_oauth_code(:display => "page")
150
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&display=page"
151
+ end
152
+
153
+ it "should raise an exception if no callback is given in initialization or the call" do
154
+ oauth2 = Koala::Facebook::OAuth.new(@app_id, @secret)
155
+ lambda { oauth2.url_for_oauth_code }.should raise_error(ArgumentError)
156
+ end
157
+ end
158
+
159
+ describe "for access token URLs" do
160
+ # url_for_access_token
161
+ it "should generate a properly formatted OAuth token URL when provided a code" do
162
+ url = @oauth.url_for_access_token(@code)
163
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{@callback_url}&client_secret=#{@secret}&code=#{@code}"
164
+ end
165
+
166
+ it "should generate a properly formatted OAuth token URL when provided a callback" do
167
+ callback = "foo.com"
168
+ url = @oauth.url_for_access_token(@code, :callback => callback)
169
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@secret}&code=#{@code}"
170
+ end
171
+ end
172
+ end
173
+
174
+ describe "for fetching access tokens" do
175
+ describe "get_access_token_info" do
176
+ it "should properly get and parse an access token token results into a hash" do
177
+ result = @oauth.get_access_token_info(@code)
178
+ result.should be_a(Hash)
179
+ end
180
+
181
+ it "should properly include the access token results" do
182
+ result = @oauth.get_access_token_info(@code)
183
+ result["access_token"].should
184
+ end
185
+
186
+ it "should raise an error when get_access_token is called with a bad code" do
187
+ lambda { @oauth.get_access_token_info("foo") }.should raise_error(Koala::Facebook::APIError)
188
+ end
189
+ end
190
+
191
+ describe "get_access_token" do
192
+ it "should use get_access_token_info to get and parse an access token token results" do
193
+ result = @oauth.get_access_token(@code)
194
+ result.should be_a(String)
195
+ end
196
+
197
+ it "should return the access token as a string" do
198
+ result = @oauth.get_access_token(@code)
199
+ original = @oauth.get_access_token_info(@code)
200
+ result.should == original["access_token"]
201
+ end
202
+
203
+ it "should raise an error when get_access_token is called with a bad code" do
204
+ lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::APIError)
205
+ end
206
+
207
+ it "should pass on any options provided to make_request" do
208
+ options = {:a => 2}
209
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::Response.new(200, "", {}))
210
+ @oauth.get_access_token(@code, options)
211
+ end
212
+ end
213
+
214
+ describe "get_app_access_token_info" do
215
+ it "should properly get and parse an app's access token as a hash" do
216
+ result = @oauth.get_app_access_token_info
217
+ result.should be_a(Hash)
218
+ end
219
+
220
+ it "should include the access token" do
221
+ result = @oauth.get_app_access_token_info
222
+ result["access_token"].should
223
+ end
224
+
225
+ it "should pass on any options provided to make_request" do
226
+ options = {:a => 2}
227
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::Response.new(200, "", {}))
228
+ @oauth.get_app_access_token_info(options)
229
+ end
230
+ end
231
+
232
+ describe "get_app_acess_token" do
233
+ it "should use get_access_token_info to get and parse an access token token results" do
234
+ result = @oauth.get_app_access_token
235
+ result.should be_a(String)
236
+ end
237
+
238
+ it "should return the access token as a string" do
239
+ result = @oauth.get_app_access_token
240
+ original = @oauth.get_app_access_token_info
241
+ result.should == original["access_token"]
242
+ end
243
+
244
+ it "should pass on any options provided to make_request" do
245
+ options = {:a => 2}
246
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::Response.new(200, "", {}))
247
+ @oauth.get_app_access_token(options)
248
+ end
249
+ end
250
+
251
+ describe "protected methods" do
252
+
253
+ # protected methods
254
+ # since these are pretty fundamental and pretty testable, we want to test them
255
+
256
+ # parse_access_token
257
+ it "should properly parse access token results" do
258
+ result = @oauth.send(:parse_access_token, @raw_token_string)
259
+ has_both_parts = result["access_token"] && result["expires"]
260
+ has_both_parts.should
261
+ end
262
+
263
+ it "should properly parse offline access token results" do
264
+ result = @oauth.send(:parse_access_token, @raw_offline_access_token_string)
265
+ has_both_parts = result["access_token"] && !result["expires"]
266
+ has_both_parts.should
267
+ end
268
+
269
+ # fetch_token_string
270
+ # somewhat duplicative with the tests for get_access_token and get_app_access_token
271
+ # but no harm in thoroughness
272
+ it "should fetch a proper token string from Facebook when given a code" do
273
+ result = @oauth.send(:fetch_token_string, :code => @code, :redirect_uri => @callback_url)
274
+ result.should =~ /^access_token/
275
+ end
276
+
277
+ it "should fetch a proper token string from Facebook when asked for the app token" do
278
+ result = @oauth.send(:fetch_token_string, {:type => 'client_cred'}, true)
279
+ result.should =~ /^access_token/
280
+ end
281
+ end
282
+ end
283
+
284
+ describe "for exchanging session keys" do
285
+ describe "with get_token_info_from_session_keys" do
286
+ it "should get an array of session keys from Facebook when passed a single key" do
287
+ result = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
288
+ result.should be_an(Array)
289
+ result.length.should == 1
290
+ end
291
+
292
+ it "should get an array of session keys from Facebook when passed multiple keys" do
293
+ result = @oauth.get_tokens_from_session_keys(@oauth_data["multiple_session_keys"])
294
+ result.should be_an(Array)
295
+ result.length.should == 2
296
+ end
297
+
298
+ it "should return the original hashes" do
299
+ result = @oauth.get_token_info_from_session_keys(@oauth_data["multiple_session_keys"])
300
+ result[0].should be_a(Hash)
301
+ end
302
+
303
+ it "should properly handle invalid session keys" do
304
+ result = @oauth.get_token_info_from_session_keys(["foo", "bar"])
305
+ #it should return nil for each of the invalid ones
306
+ result.each {|r| r.should be_nil}
307
+ end
308
+
309
+ it "should properly handle a mix of valid and invalid session keys" do
310
+ result = @oauth.get_token_info_from_session_keys(["foo"].concat(@oauth_data["multiple_session_keys"]))
311
+ # it should return nil for each of the invalid ones
312
+ result.each_with_index {|r, index| index > 0 ? r.should(be_a(Hash)) : r.should(be_nil)}
313
+ end
314
+
315
+ it "should throw an APIError if Facebook returns an empty body (as happens for instance when the API breaks)" do
316
+ @oauth.should_receive(:fetch_token_string).and_return("")
317
+ lambda { @oauth.get_token_info_from_session_keys(@oauth_data["multiple_session_keys"]) }.should raise_error(Koala::Facebook::APIError)
318
+ end
319
+
320
+ it "should pass on any options provided to make_request" do
321
+ options = {:a => 2}
322
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::Response.new(200, "[{}]", {}))
323
+ @oauth.get_token_info_from_session_keys([], options)
324
+ end
325
+ end
326
+
327
+ describe "with get_tokens_from_session_keys" do
328
+ it "should call get_token_info_from_session_keys" do
329
+ args = @oauth_data["multiple_session_keys"]
330
+ @oauth.should_receive(:get_token_info_from_session_keys).with(args, anything).and_return([])
331
+ @oauth.get_tokens_from_session_keys(args)
332
+ end
333
+
334
+ it "should return an array of strings" do
335
+ args = @oauth_data["multiple_session_keys"]
336
+ result = @oauth.get_tokens_from_session_keys(args)
337
+ result.each {|r| r.should be_a(String) }
338
+ end
339
+
340
+ it "should properly handle invalid session keys" do
341
+ result = @oauth.get_tokens_from_session_keys(["foo", "bar"])
342
+ # it should return nil for each of the invalid ones
343
+ result.each {|r| r.should be_nil}
344
+ end
345
+
346
+ it "should properly handle a mix of valid and invalid session keys" do
347
+ result = @oauth.get_tokens_from_session_keys(["foo"].concat(@oauth_data["multiple_session_keys"]))
348
+ # it should return nil for each of the invalid ones
349
+ result.each_with_index {|r, index| index > 0 ? r.should(be_a(String)) : r.should(be_nil)}
350
+ end
351
+
352
+ it "should pass on any options provided to make_request" do
353
+ options = {:a => 2}
354
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::Response.new(200, "[{}]", {}))
355
+ @oauth.get_tokens_from_session_keys([], options)
356
+ end
357
+ end
358
+
359
+ describe "get_token_from_session_key" do
360
+ it "should call get_tokens_from_session_keys when the get_token_from_session_key is called" do
361
+ key = @oauth_data["session_key"]
362
+ @oauth.should_receive(:get_tokens_from_session_keys).with([key], anything).and_return([])
363
+ @oauth.get_token_from_session_key(key)
364
+ end
365
+
366
+ it "should get back the access token string from get_token_from_session_key" do
367
+ result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
368
+ result.should be_a(String)
369
+ end
370
+
371
+ it "should be the first value in the array" do
372
+ result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
373
+ array = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
374
+ result.should == array[0]
375
+ end
376
+
377
+ it "should properly handle an invalid session key" do
378
+ result = @oauth.get_token_from_session_key("foo")
379
+ result.should be_nil
380
+ end
381
+
382
+ it "should pass on any options provided to make_request" do
383
+ options = {:a => 2}
384
+ Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(options)).and_return(Koala::Response.new(200, "[{}]", {}))
385
+ @oauth.get_token_from_session_key("", options)
386
+ end
387
+ end
388
+ end
389
+
390
+ describe "for parsing signed requests" do
391
+ # the signed request code is ported directly from Facebook
392
+ # so we only need to test at a high level that it works
393
+ it "should throw an error if the algorithm is unsupported" do
394
+ JSON.stub!(:parse).and_return("algorithm" => "my fun algorithm")
395
+ lambda { @oauth.parse_signed_request(@signed_request) }.should raise_error
396
+ end
397
+
398
+ it "should throw an error if the signature is invalid" do
399
+ OpenSSL::HMAC.stub!(:hexdigest).and_return("i'm an invalid signature")
400
+ lambda { @oauth.parse_signed_request(@signed_request) }.should raise_error
401
+ end
402
+
403
+ it "properly parses requests" do
404
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret || @app_secret)
405
+ @oauth.parse_signed_request(@signed_params).should == @signed_params_result
406
+ end
407
+ end
408
+
409
+ end # describe
@@ -0,0 +1,184 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Koala::Facebook::RealtimeUpdates" do
4
+ before :all do
5
+ # get oauth data
6
+ @oauth_data = $testing_data["oauth_test_data"]
7
+ @app_id = @oauth_data["app_id"]
8
+ @secret = @oauth_data["secret"]
9
+ @callback_url = @oauth_data["callback_url"]
10
+ @app_access_token = @oauth_data["app_access_token"]
11
+
12
+ # check OAuth data
13
+ unless @app_id && @secret && @callback_url && @app_access_token
14
+ raise Exception, "Must supply OAuth app id, secret, app_access_token, and callback to run live subscription tests!"
15
+ end
16
+
17
+ # get subscription data
18
+ @subscription_data = $testing_data["subscription_test_data"]
19
+ @verify_token = @subscription_data["verify_token"]
20
+ @challenge_data = @subscription_data["challenge_data"]
21
+ @subscription_path = @subscription_data["subscription_path"]
22
+
23
+ # check subscription data
24
+ unless @verify_token && @challenge_data && @subscription_path
25
+ raise Exception, "Must supply verify_token and equivalent challenge_data to run live subscription tests!"
26
+ end
27
+ end
28
+
29
+ describe "when initializing" do
30
+ # basic initialization
31
+ it "should initialize properly with an app_id and an app_access_token" do
32
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
33
+ updates.should be_a(Koala::Facebook::RealtimeUpdates)
34
+ end
35
+
36
+ # attributes
37
+ it "should allow read access to app_id, app_access_token, and secret" do
38
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
39
+ # this should not throw errors
40
+ updates.app_id && updates.app_access_token && updates.secret
41
+ end
42
+
43
+ it "should not allow write access to app_id" do
44
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
45
+ # this should not throw errors
46
+ lambda { updates.app_id = 2 }.should raise_error(NoMethodError)
47
+ end
48
+
49
+ it "should not allow write access to app_access_token" do
50
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
51
+ # this should not throw errors
52
+ lambda { updates.app_access_token = 2 }.should raise_error(NoMethodError)
53
+ end
54
+
55
+ it "should not allow write access to secret" do
56
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
57
+ # this should not throw errors
58
+ lambda { updates.secret = 2 }.should raise_error(NoMethodError)
59
+ end
60
+
61
+ # init with secret / fetching the token
62
+ it "should initialize properly with an app_id and a secret" do
63
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
64
+ updates.should be_a(Koala::Facebook::RealtimeUpdates)
65
+ end
66
+
67
+ it "should fetch an app_token from Facebook when provided an app_id and a secret" do
68
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
69
+ updates.app_access_token.should_not be_nil
70
+ end
71
+
72
+ it "should use the OAuth class to fetch a token when provided an app_id and a secret" do
73
+ oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
74
+ token = oauth.get_app_access_token
75
+ oauth.should_receive(:get_app_access_token).and_return(token)
76
+ Koala::Facebook::OAuth.should_receive(:new).with(@app_id, @secret).and_return(oauth)
77
+ updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
78
+ end
79
+ end
80
+
81
+ describe "when used" do
82
+ before :each do
83
+ @updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
84
+ end
85
+
86
+ it "should send a subscription request to a valid server" do
87
+ result = @updates.subscribe("user", "name", @subscription_path, @verify_token)
88
+ result.should be_true
89
+ end
90
+
91
+ it "should send a subscription request to a valid server" do
92
+ result = @updates.subscribe("user", "name", @subscription_path, @verify_token)
93
+ result.should be_true
94
+ end
95
+
96
+ it "should send a subscription request to an invalid path on a valid server" do
97
+ lambda { result = @updates.subscribe("user", "name", @subscription_path + "foo", @verify_token) }.should raise_exception(Koala::Facebook::APIError)
98
+ end
99
+
100
+ it "should fail to send a subscription request to an invalid server" do
101
+ lambda { @updates.subscribe("user", "name", "foo", @verify_token) }.should raise_exception(Koala::Facebook::APIError)
102
+ end
103
+
104
+ it "should unsubscribe a valid individual object successfully" do
105
+ @updates.unsubscribe("user").should be_true
106
+ end
107
+
108
+ it "should unsubscribe all subscriptions successfully" do
109
+ @updates.unsubscribe.should be_true
110
+ end
111
+
112
+ it "should fail when an invalid object is provided to unsubscribe" do
113
+ lambda { @updates.unsubscribe("kittens") }.should raise_error(Koala::Facebook::APIError)
114
+ end
115
+
116
+ it "should is subscriptions properly" do
117
+ @updates.list_subscriptions.should be_a(Array)
118
+ end
119
+ end # describe "when used"
120
+
121
+ describe "when meeting challenge" do
122
+ it "should return false if hub.mode isn't subscribe" do
123
+ params = {'hub.mode' => 'not subscribe'}
124
+ Koala::Facebook::RealtimeUpdates.meet_challenge(params).should be_false
125
+ end
126
+
127
+ it "should return false if not given a verify_token or block" do
128
+ params = {'hub.mode' => 'subscribe'}
129
+ Koala::Facebook::RealtimeUpdates.meet_challenge(params).should be_false
130
+ end
131
+
132
+ describe "and mode is 'subscribe'" do
133
+ before(:each) do
134
+ @params = {'hub.mode' => 'subscribe'}
135
+ end
136
+
137
+ describe "and a token is given" do
138
+ before(:each) do
139
+ @token = 'token'
140
+ @params['hub.verify_token'] = @token
141
+ end
142
+
143
+ it "should return false if the given verify token doesn't match" do
144
+ Koala::Facebook::RealtimeUpdates.meet_challenge(@params, @token + '1').should be_false
145
+ end
146
+
147
+ it "should return the challenge if the given verify token matches" do
148
+ @params['hub.challenge'] = 'challenge val'
149
+ Koala::Facebook::RealtimeUpdates.meet_challenge(@params, @token).should == @params['hub.challenge']
150
+ end
151
+ end
152
+
153
+ describe "and a block is given" do
154
+ it "should give the block the token as a parameter" do
155
+ Koala::Facebook::RealtimeUpdates.meet_challenge(@params)do |token|
156
+ token.should == @token
157
+ end
158
+ end
159
+
160
+ it "should return false if the given block return false" do
161
+ Koala::Facebook::RealtimeUpdates.meet_challenge(@params)do |token|
162
+ false
163
+ end.should be_false
164
+ end
165
+
166
+ it "should return false if the given block returns nil" do
167
+ Koala::Facebook::RealtimeUpdates.meet_challenge(@params)do |token|
168
+ nil
169
+ end.should be_false
170
+ end
171
+
172
+ it "should return the challenge if the given block returns true" do
173
+ @params['hub.challenge'] = 'challenge val'
174
+ Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
175
+ true
176
+ end.should be_true
177
+ end
178
+ end
179
+
180
+ end # describe "and mode is subscribe"
181
+
182
+ end # describe "when meeting challenge"
183
+
184
+ end # describe
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Koala::Facebook::RestAPI" do
4
+
5
+ context "without an access token" do
6
+ before :each do
7
+ @api = Koala::Facebook::RestAPI.new
8
+ end
9
+
10
+ it_should_behave_like "Koala RestAPI"
11
+ it_should_behave_like "Koala RestAPI without an access token"
12
+ end
13
+
14
+ context "with an access token" do
15
+ include LiveTestingDataHelper
16
+
17
+ before :each do
18
+ @api = Koala::Facebook::RestAPI.new(@token)
19
+ end
20
+
21
+ it_should_behave_like "Koala RestAPI"
22
+ it_should_behave_like "Koala RestAPI with an access token"
23
+ end
24
+
25
+ end