tyler_koala 1.2.0beta

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