tyler_koala 1.2.0beta

Sign up to get free protection for your applications and to get access to all the features.
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