koala 1.5.0 → 1.6.0.rc1
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/.gitignore +2 -1
- data/.travis.yml +4 -1
- data/Gemfile +1 -1
- data/changelog.md +293 -0
- data/koala.gemspec +3 -2
- data/lib/koala.rb +1 -2
- data/lib/koala/api.rb +11 -31
- data/lib/koala/api/batch_operation.rb +1 -1
- data/lib/koala/api/graph_api.rb +132 -62
- data/lib/koala/api/graph_batch_api.rb +28 -38
- data/lib/koala/api/graph_collection.rb +3 -1
- data/lib/koala/api/rest_api.rb +19 -3
- data/lib/koala/errors.rb +86 -0
- data/lib/koala/oauth.rb +21 -21
- data/lib/koala/realtime_updates.rb +42 -21
- data/lib/koala/version.rb +1 -1
- data/readme.md +130 -103
- data/spec/cases/api_spec.rb +3 -3
- data/spec/cases/error_spec.rb +91 -20
- data/spec/cases/graph_api_batch_spec.rb +57 -22
- data/spec/cases/graph_api_spec.rb +68 -0
- data/spec/cases/graph_collection_spec.rb +6 -0
- data/spec/cases/oauth_spec.rb +16 -16
- data/spec/cases/realtime_updates_spec.rb +80 -82
- data/spec/cases/test_users_spec.rb +21 -18
- data/spec/fixtures/mock_facebook_responses.yml +45 -29
- data/spec/spec_helper.rb +6 -6
- data/spec/support/graph_api_shared_examples.rb +13 -13
- data/spec/support/koala_test.rb +13 -13
- data/spec/support/rest_api_shared_examples.rb +3 -3
- metadata +30 -14
- data/CHANGELOG +0 -275
@@ -381,58 +381,56 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
381
381
|
}.to raise_exception(Koala::Facebook::APIError)
|
382
382
|
end
|
383
383
|
|
384
|
-
it "raises
|
384
|
+
it "raises a BadFacebookResponse if the body is empty" do
|
385
385
|
Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(200, "", {}))
|
386
386
|
expect {
|
387
387
|
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
388
|
-
}.to raise_exception(Koala::Facebook::
|
388
|
+
}.to raise_exception(Koala::Facebook::BadFacebookResponse)
|
389
389
|
end
|
390
390
|
|
391
391
|
context "with the old style" do
|
392
392
|
before :each do
|
393
|
-
Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(
|
393
|
+
Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(400, '{"error_code":190,"error_description":"Error validating access token."}', {}))
|
394
394
|
end
|
395
395
|
|
396
|
-
it "throws an error
|
396
|
+
it "throws an error" do
|
397
397
|
expect {
|
398
398
|
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
399
399
|
}.to raise_exception(Koala::Facebook::APIError)
|
400
400
|
end
|
401
401
|
|
402
|
-
it "
|
402
|
+
it "passes all the error details" do
|
403
403
|
begin
|
404
404
|
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
405
405
|
rescue Koala::Facebook::APIError => err
|
406
|
+
err.fb_error_code.should == 190
|
407
|
+
err.fb_error_message.should == "Error validating access token."
|
408
|
+
err.http_status == 400
|
409
|
+
err.response_body == '{"error_code":190,"error_description":"Error validating access token."}'
|
406
410
|
end
|
407
|
-
err.fb_error_type.should
|
408
|
-
end
|
409
|
-
|
410
|
-
it "passes all the error details if an old Batch API-style error is raised" do
|
411
|
-
begin
|
412
|
-
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
413
|
-
rescue Koala::Facebook::APIError => err
|
414
|
-
end
|
415
|
-
err.raw_response["error"].should == 190
|
416
411
|
end
|
417
412
|
end
|
418
413
|
|
419
414
|
context "with the new style" do
|
420
415
|
before :each do
|
421
|
-
Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(
|
416
|
+
Koala.stub(:make_request).and_return(Koala::HTTPService::Response.new(400, '{"error":{"message":"Request 0 cannot depend on an unresolved request with name f. Requests can only depend on preceding requests","type":"GraphBatchException"}}', {}))
|
422
417
|
end
|
423
418
|
|
424
|
-
it "throws an error
|
419
|
+
it "throws an error" do
|
425
420
|
expect {
|
426
421
|
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
427
422
|
}.to raise_exception(Koala::Facebook::APIError)
|
428
423
|
end
|
429
424
|
|
430
|
-
it "passes all the error details
|
425
|
+
it "passes all the error details" do
|
431
426
|
begin
|
432
427
|
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
433
428
|
rescue Koala::Facebook::APIError => err
|
429
|
+
err.fb_error_type.should == "GraphBatchException"
|
430
|
+
err.fb_error_message.should == "Request 0 cannot depend on an unresolved request with name f. Requests can only depend on preceding requests"
|
431
|
+
err.http_status == 400
|
432
|
+
err.response_body == '{"error":{"message":"Request 0 cannot depend on an unresolved request with name f. Requests can only depend on preceding requests","type":"GraphBatchException"}}'
|
434
433
|
end
|
435
|
-
err.raw_response["message"].should
|
436
434
|
end
|
437
435
|
end
|
438
436
|
end
|
@@ -509,7 +507,8 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
509
507
|
pictures = @api.batch do |batch_api|
|
510
508
|
batch_api.get_picture('me')
|
511
509
|
end
|
512
|
-
pictures.
|
510
|
+
puts pictures.inspect
|
511
|
+
pictures.first.should =~ /http\:\/\// # works both live & stubbed
|
513
512
|
end
|
514
513
|
|
515
514
|
it "handles requests for two different tokens" do
|
@@ -526,7 +525,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
526
525
|
batch_api.get_connection("2", "invalidconnection")
|
527
526
|
batch_api.get_object(KoalaTest.user1, {}, {"access_token" => @app_api.access_token})
|
528
527
|
end
|
529
|
-
failed_call.should be_a(Koala::Facebook::
|
528
|
+
failed_call.should be_a(Koala::Facebook::ClientError)
|
530
529
|
koppel["id"].should_not be_nil
|
531
530
|
end
|
532
531
|
|
@@ -550,6 +549,42 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
550
549
|
fql_result[0]["first_name"].should == "Alex"
|
551
550
|
end
|
552
551
|
|
552
|
+
describe 'with post-processing callback' do
|
553
|
+
let(:me_result) { stub("me result") }
|
554
|
+
let(:friends_result) { stub("friends result") }
|
555
|
+
|
556
|
+
let(:me_callback) { lambda {|data| me_result } }
|
557
|
+
let(:friends_callback) { lambda {|data| friends_result } }
|
558
|
+
|
559
|
+
it 'calls the callback with the appropriate data' do
|
560
|
+
me_callback.should_receive(:call).with(hash_including(
|
561
|
+
'id' => KoalaTest.user1
|
562
|
+
))
|
563
|
+
friends_callback.should_receive(:call).with([
|
564
|
+
hash_including('id' => KoalaTest.user2)
|
565
|
+
])
|
566
|
+
@api.batch do |batch_api|
|
567
|
+
batch_api.get_object('me', &me_callback)
|
568
|
+
batch_api.get_connections('me', 'friends', &friends_callback)
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
it 'passes GraphCollections, not raw data' do
|
573
|
+
friends_callback.should_receive(:call).with(kind_of(Koala::Facebook::API::GraphCollection))
|
574
|
+
@api.batch do |batch_api|
|
575
|
+
batch_api.get_object('me')
|
576
|
+
batch_api.get_connections('me', 'friends', &friends_callback)
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
it "returns the result of the callback" do
|
581
|
+
@api.batch do |batch_api|
|
582
|
+
batch_api.get_object('me', &me_callback)
|
583
|
+
batch_api.get_connections('me', 'friends', &friends_callback)
|
584
|
+
end.should == [me_result, friends_result]
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
553
588
|
describe "binary files" do
|
554
589
|
it "posts binary files" do
|
555
590
|
file = File.open(File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg"))
|
@@ -614,7 +649,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
614
649
|
batch_api.get_object(KoalaTest.user1, {}, :batch_args => {:depends_on => "getdata"})
|
615
650
|
end
|
616
651
|
|
617
|
-
failed_call.should be_a(Koala::Facebook::
|
652
|
+
failed_call.should be_a(Koala::Facebook::ClientError)
|
618
653
|
koppel.should be_nil
|
619
654
|
end
|
620
655
|
|
@@ -624,7 +659,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
624
659
|
batch_api.get_connections("me", "friends", {:limit => 5})
|
625
660
|
batch_api.get_objects("{result=i-dont-exist:$.data.*.id}")
|
626
661
|
end
|
627
|
-
}.to raise_exception(Koala::Facebook::
|
662
|
+
}.to raise_exception(Koala::Facebook::ClientError)
|
628
663
|
end
|
629
664
|
end
|
630
665
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Koala::Facebook::GraphAPIMethods' do
|
4
|
+
before do
|
5
|
+
@api = Koala::Facebook::API.new(@token)
|
6
|
+
# app API
|
7
|
+
@app_id = KoalaTest.app_id
|
8
|
+
@app_access_token = KoalaTest.app_access_token
|
9
|
+
@app_api = Koala::Facebook::API.new(@app_access_token)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'post-processing for' do
|
13
|
+
let(:post_processing) { lambda {} }
|
14
|
+
|
15
|
+
# Most API methods have the same signature, we test get_object representatively
|
16
|
+
# and the other methods which do some post-processing locally
|
17
|
+
context '#get_object' do
|
18
|
+
it 'returns result of block' do
|
19
|
+
result = {"id" => 1, "name" => 1, "updated_time" => 1}
|
20
|
+
@api.stub(:api).and_return(result)
|
21
|
+
post_processing.should_receive(:call).
|
22
|
+
with(result).and_return('new result')
|
23
|
+
@api.get_object('koppel', &post_processing).should == 'new result'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context '#get_picture' do
|
28
|
+
it 'returns result of block' do
|
29
|
+
result = "http://facebook.com/"
|
30
|
+
@api.stub(:api).and_return("Location" => result)
|
31
|
+
post_processing.should_receive(:call).
|
32
|
+
with(result).and_return('new result')
|
33
|
+
@api.get_picture('lukeshepard', &post_processing).should == 'new result'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context '#fql_multiquery' do
|
38
|
+
before do
|
39
|
+
@api.should_receive(:get_object).and_return([
|
40
|
+
{"name" => "query1", "fql_result_set" => [{"id" => 123}]},
|
41
|
+
{"name" => "query2", "fql_result_set" => ["id" => 456]}
|
42
|
+
])
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'is called with resolved response' do
|
46
|
+
resolved_result = {
|
47
|
+
'query1' => [{'id' => 123}],
|
48
|
+
'query2' => [{'id'=>456}]
|
49
|
+
}
|
50
|
+
post_processing.should_receive(:call).
|
51
|
+
with(resolved_result).and_return('id'=>'123', 'id'=>'456')
|
52
|
+
@api.fql_multiquery({}, &post_processing).should ==
|
53
|
+
{'id'=>'123', 'id'=>'456'}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context '#get_page_access_token' do
|
58
|
+
it 'returns result of block' do
|
59
|
+
token = Koala::MockHTTPService::APP_ACCESS_TOKEN
|
60
|
+
@api.stub(:api).and_return("access_token" => token)
|
61
|
+
post_processing.should_receive(:call).
|
62
|
+
with(token).and_return('base64-encoded access token')
|
63
|
+
@api.get_page_access_token('facebook', &post_processing).should ==
|
64
|
+
'base64-encoded access token'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -104,6 +104,12 @@ describe Koala::Facebook::GraphCollection do
|
|
104
104
|
args_hash = {"one" => "val_one", "two" => "val_two"}
|
105
105
|
Koala::Facebook::GraphCollection.parse_page_url("http://facebook.com/#{base}?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").should == [base, args_hash]
|
106
106
|
end
|
107
|
+
|
108
|
+
it "works with addresses with irregular characters" do
|
109
|
+
access_token = "appid123a|fdcba"
|
110
|
+
base, args_hash = Koala::Facebook::GraphCollection.parse_page_url("http://facebook.com/foo?token=#{access_token}")
|
111
|
+
args_hash["token"].should == access_token
|
112
|
+
end
|
107
113
|
end
|
108
114
|
end
|
109
115
|
|
data/spec/cases/oauth_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Koala::Facebook::OAuth" do
|
4
|
-
before :
|
4
|
+
before :all do
|
5
5
|
# make the relevant test data easily accessible
|
6
6
|
@app_id = KoalaTest.app_id
|
7
7
|
@secret = KoalaTest.secret
|
@@ -24,7 +24,9 @@ describe "Koala::Facebook::OAuth" do
|
|
24
24
|
@multiple_session_keys = [KoalaTest.session_key, KoalaTest.session_key] if KoalaTest.session_key
|
25
25
|
|
26
26
|
@oauth = Koala::Facebook::OAuth.new(@app_id, @secret, @callback_url)
|
27
|
+
end
|
27
28
|
|
29
|
+
before :each do
|
28
30
|
@time = Time.now
|
29
31
|
Time.stub!(:now).and_return(@time)
|
30
32
|
@time.stub!(:to_i).and_return(1273363199)
|
@@ -117,19 +119,16 @@ describe "Koala::Facebook::OAuth" do
|
|
117
119
|
end
|
118
120
|
|
119
121
|
it "returns nil if the call to FB returns an expired code error" do
|
120
|
-
@oauth.stub(:get_access_token_info).and_raise(Koala::Facebook::
|
121
|
-
"
|
122
|
-
"message" => "Code was invalid or expired. Session has expired at unix time 1324044000. The current unix time is 1324300957."
|
122
|
+
@oauth.stub(:get_access_token_info).and_raise(Koala::Facebook::OAuthTokenRequestError.new(400,
|
123
|
+
'{ "error": { "type": "OAuthException", "message": "Code was invalid or expired. Session has expired at unix time 1324044000. The current unix time is 1324300957." } }'
|
123
124
|
))
|
124
125
|
@oauth.get_user_info_from_cookies(@cookie).should be_nil
|
125
126
|
end
|
126
127
|
|
127
128
|
it "raises the error if the call to FB returns a different error" do
|
128
|
-
@oauth.stub(:get_access_token_info).and_raise(Koala::Facebook::
|
129
|
-
"
|
130
|
-
|
131
|
-
))
|
132
|
-
expect { @oauth.get_user_info_from_cookies(@cookie) }.to raise_exception(Koala::Facebook::APIError)
|
129
|
+
@oauth.stub(:get_access_token_info).and_raise(Koala::Facebook::OAuthTokenRequestError.new(400,
|
130
|
+
'{ "error": { "type": "OtherError", "message": "A Facebook Error" } }'))
|
131
|
+
expect { @oauth.get_user_info_from_cookies(@cookie) }.to raise_exception(Koala::Facebook::OAuthTokenRequestError)
|
133
132
|
end
|
134
133
|
end
|
135
134
|
|
@@ -149,6 +148,7 @@ describe "Koala::Facebook::OAuth" do
|
|
149
148
|
|
150
149
|
it "returns all the cookie components from valid cookie string" do
|
151
150
|
cookie_data = KoalaTest.oauth_test_data["valid_cookies"]
|
151
|
+
puts cookie_data.inspect
|
152
152
|
parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
|
153
153
|
number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
|
154
154
|
parsing_results.length.should == number_of_components
|
@@ -295,13 +295,13 @@ describe "Koala::Facebook::OAuth" do
|
|
295
295
|
|
296
296
|
it "generates a properly formatted OAuth token URL when provided a code" do
|
297
297
|
url = @oauth.url_for_access_token(@code)
|
298
|
-
url.should match_url("https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&code=#{@code}&client_secret=#{@secret}&redirect_uri=#{CGI.escape @callback_url}")
|
298
|
+
url.should match_url("https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&code=#{@code}&client_secret=#{@secret}&redirect_uri=#{CGI.escape @callback_url}")
|
299
299
|
end
|
300
300
|
|
301
301
|
it "generates a properly formatted OAuth token URL when provided a callback" do
|
302
302
|
callback = "foo.com"
|
303
303
|
url = @oauth.url_for_access_token(@code, :callback => callback)
|
304
|
-
url.should match_url("https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&code=#{@code}&client_secret=#{@secret}&redirect_uri=#{CGI.escape callback}")
|
304
|
+
url.should match_url("https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&code=#{@code}&client_secret=#{@secret}&redirect_uri=#{CGI.escape callback}")
|
305
305
|
end
|
306
306
|
|
307
307
|
it "includes any additional options as URL parameters, appropriately escaped" do
|
@@ -399,7 +399,7 @@ describe "Koala::Facebook::OAuth" do
|
|
399
399
|
end
|
400
400
|
|
401
401
|
it "raises an error when get_access_token is called with a bad code" do
|
402
|
-
lambda { @oauth.get_access_token_info("foo") }.should raise_error(Koala::Facebook::
|
402
|
+
lambda { @oauth.get_access_token_info("foo") }.should raise_error(Koala::Facebook::OAuthTokenRequestError)
|
403
403
|
end
|
404
404
|
end
|
405
405
|
end
|
@@ -425,7 +425,7 @@ describe "Koala::Facebook::OAuth" do
|
|
425
425
|
end
|
426
426
|
|
427
427
|
it "raises an error when get_access_token is called with a bad code" do
|
428
|
-
lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::
|
428
|
+
lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::OAuthTokenRequestError)
|
429
429
|
end
|
430
430
|
end
|
431
431
|
end
|
@@ -493,7 +493,7 @@ describe "Koala::Facebook::OAuth" do
|
|
493
493
|
end
|
494
494
|
|
495
495
|
it "raises an error when exchange_access_token_info is called with a bad code" do
|
496
|
-
lambda { @oauth.exchange_access_token_info("foo") }.should raise_error(Koala::Facebook::
|
496
|
+
lambda { @oauth.exchange_access_token_info("foo") }.should raise_error(Koala::Facebook::OAuthTokenRequestError)
|
497
497
|
end
|
498
498
|
end
|
499
499
|
|
@@ -579,9 +579,9 @@ describe "Koala::Facebook::OAuth" do
|
|
579
579
|
result.each_with_index {|r, index| index > 0 ? r.should(be_a(Hash)) : r.should(be_nil)}
|
580
580
|
end
|
581
581
|
|
582
|
-
it "throws
|
582
|
+
it "throws a BadFacebookResponse if Facebook returns an empty body (as happens for instance when the API breaks)" do
|
583
583
|
@oauth.should_receive(:fetch_token_string).and_return("")
|
584
|
-
lambda { @oauth.get_token_info_from_session_keys(@multiple_session_keys) }.should raise_error(Koala::Facebook::
|
584
|
+
lambda { @oauth.get_token_info_from_session_keys(@multiple_session_keys) }.should raise_error(Koala::Facebook::BadFacebookResponse)
|
585
585
|
end
|
586
586
|
|
587
587
|
it "passes on any options provided to make_request" do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'base64'
|
2
3
|
|
3
4
|
describe "Koala::Facebook::RealtimeUpdates" do
|
4
5
|
before :all do
|
@@ -7,24 +8,24 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
7
8
|
@secret = KoalaTest.secret
|
8
9
|
@callback_url = KoalaTest.oauth_test_data["callback_url"]
|
9
10
|
@app_access_token = KoalaTest.app_access_token
|
10
|
-
|
11
|
+
|
11
12
|
# check OAuth data
|
12
13
|
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
|
+
raise Exception, "Must supply OAuth app id, secret, app_access_token, and callback to run live subscription tests!"
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
# get subscription data
|
17
18
|
@verify_token = KoalaTest.subscription_test_data["verify_token"]
|
18
19
|
@challenge_data = KoalaTest.subscription_test_data["challenge_data"]
|
19
20
|
@subscription_path = KoalaTest.subscription_test_data["subscription_path"]
|
20
|
-
|
21
|
+
|
21
22
|
# check subscription data
|
22
23
|
unless @verify_token && @challenge_data && @subscription_path
|
23
|
-
raise Exception, "Must supply verify_token and equivalent challenge_data to run subscription tests!"
|
24
|
+
raise Exception, "Must supply verify_token and equivalent challenge_data to run subscription tests!"
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
before :each do
|
28
|
+
before :each do
|
28
29
|
@updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
29
30
|
end
|
30
31
|
|
@@ -34,28 +35,28 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
34
35
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
35
36
|
updates.should be_a(Koala::Facebook::RealtimeUpdates)
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
# attributes
|
39
40
|
it "allows read access to app_id" do
|
40
|
-
# in Ruby 1.9, .method returns symbols
|
41
|
+
# in Ruby 1.9, .method returns symbols
|
41
42
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should include(:app_id)
|
42
43
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should_not include(:app_id=)
|
43
44
|
end
|
44
45
|
|
45
46
|
it "allows read access to app_access_token" do
|
46
|
-
# in Ruby 1.9, .method returns symbols
|
47
|
+
# in Ruby 1.9, .method returns symbols
|
47
48
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should include(:app_access_token)
|
48
49
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should_not include(:app_access_token=)
|
49
50
|
end
|
50
51
|
|
51
52
|
it "allows read access to secret" do
|
52
|
-
# in Ruby 1.9, .method returns symbols
|
53
|
+
# in Ruby 1.9, .method returns symbols
|
53
54
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should include(:secret)
|
54
55
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should_not include(:secret=)
|
55
56
|
end
|
56
57
|
|
57
58
|
it "allows read access to api" do
|
58
|
-
# in Ruby 1.9, .method returns symbols
|
59
|
+
# in Ruby 1.9, .method returns symbols
|
59
60
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should include(:api)
|
60
61
|
Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym).should_not include(:api=)
|
61
62
|
end
|
@@ -71,35 +72,35 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
71
72
|
Koala::Utils.should_receive(:deprecate)
|
72
73
|
updates.graph_api
|
73
74
|
end
|
74
|
-
|
75
|
+
|
75
76
|
# init with secret / fetching the token
|
76
|
-
it "initializes properly with an app_id and a secret" do
|
77
|
+
it "initializes properly with an app_id and a secret" do
|
77
78
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
78
|
-
updates.should be_a(Koala::Facebook::RealtimeUpdates)
|
79
|
+
updates.should be_a(Koala::Facebook::RealtimeUpdates)
|
79
80
|
end
|
80
81
|
|
81
|
-
it "fetches an app_token from Facebook when provided an app_id and a secret" do
|
82
|
+
it "fetches an app_token from Facebook when provided an app_id and a secret" do
|
82
83
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
83
84
|
updates.app_access_token.should_not be_nil
|
84
85
|
end
|
85
|
-
|
86
|
+
|
86
87
|
it "uses the OAuth class to fetch a token when provided an app_id and a secret" do
|
87
88
|
oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
|
88
89
|
token = oauth.get_app_access_token
|
89
90
|
oauth.should_receive(:get_app_access_token).and_return(token)
|
90
|
-
Koala::Facebook::OAuth.should_receive(:new).with(@app_id, @secret).and_return(oauth)
|
91
|
+
Koala::Facebook::OAuth.should_receive(:new).with(@app_id, @secret).and_return(oauth)
|
91
92
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
92
93
|
end
|
93
|
-
|
94
|
-
it "sets up the with the app acces token" do
|
94
|
+
|
95
|
+
it "sets up the with the app acces token" do
|
95
96
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
96
97
|
updates.api.should be_a(Koala::Facebook::API)
|
97
98
|
updates.api.access_token.should == @app_access_token
|
98
|
-
end
|
99
|
-
|
99
|
+
end
|
100
|
+
|
100
101
|
end
|
101
102
|
|
102
|
-
describe "#subscribe" do
|
103
|
+
describe "#subscribe" do
|
103
104
|
it "makes a POST to the subscription path" do
|
104
105
|
@updates.api.should_receive(:graph_call).with(@updates.subscription_path, anything, "post", anything)
|
105
106
|
@updates.subscribe("user", "name", @subscription_path, @verify_token)
|
@@ -112,11 +113,11 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
112
113
|
:object => obj,
|
113
114
|
:fields => fields,
|
114
115
|
:callback_url => @subscription_path,
|
115
|
-
:verify_token => @verify_token
|
116
|
+
:verify_token => @verify_token
|
116
117
|
), anything, anything)
|
117
118
|
@updates.subscribe("user", "name", @subscription_path, @verify_token)
|
118
119
|
end
|
119
|
-
|
120
|
+
|
120
121
|
pending "doesn't require a verify_token" do
|
121
122
|
# see https://github.com/arsduo/koala/issues/150
|
122
123
|
obj = "user"
|
@@ -124,50 +125,36 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
124
125
|
@updates.api.should_not_receive(:graph_call).with(anything, hash_including(:verify_token => anything), anything, anything)
|
125
126
|
@updates.subscribe("user", "name", @subscription_path)
|
126
127
|
end
|
127
|
-
|
128
|
+
|
128
129
|
it "requires verify_token" do
|
129
130
|
expect { @updates.subscribe("user", "name", @subscription_path) }.to raise_exception
|
130
131
|
end
|
131
|
-
|
132
|
-
it "requests the status component" do
|
133
|
-
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(:http_component => :status))
|
134
|
-
@updates.subscribe("user", "name", @subscription_path, @verify_token)
|
135
|
-
end
|
136
|
-
|
132
|
+
|
137
133
|
it "accepts an options hash" do
|
138
134
|
options = {:a => 2, :b => "c"}
|
139
135
|
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
140
136
|
@updates.subscribe("user", "name", @subscription_path, @verify_token, options)
|
141
137
|
end
|
142
|
-
|
143
|
-
it "overrides any provided http_component" do
|
144
|
-
# since we test against status, we need to ensure that we get that
|
145
|
-
options = {:http_component => :body}
|
146
|
-
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(:http_component => :status))
|
147
|
-
@updates.subscribe("user", "name", @subscription_path, @verify_token, options)
|
148
|
-
end
|
149
138
|
|
150
139
|
describe "in practice" do
|
151
140
|
it "sends a subscription request" do
|
152
|
-
|
153
|
-
result.should be_true
|
141
|
+
expect { @updates.subscribe("user", "name", @subscription_path, @verify_token) }.to_not raise_error
|
154
142
|
end
|
155
|
-
|
143
|
+
|
156
144
|
pending "sends a subscription request without a verify token" do
|
157
|
-
|
158
|
-
result.should be_true
|
145
|
+
expect { @updates.subscribe("user", "name", @subscription_path) }.to_not raise_error
|
159
146
|
end
|
160
|
-
|
147
|
+
|
161
148
|
it "fails if you try to hit an invalid path on your valid server" do
|
162
149
|
expect { result = @updates.subscribe("user", "name", @subscription_path + "foo", @verify_token) }.to raise_exception(Koala::Facebook::APIError)
|
163
150
|
end
|
164
|
-
|
151
|
+
|
165
152
|
it "fails to send a subscription request to an invalid server" do
|
166
153
|
expect { @updates.subscribe("user", "name", "foo", @verify_token) }.to raise_exception(Koala::Facebook::APIError)
|
167
154
|
end
|
168
155
|
end
|
169
156
|
end
|
170
|
-
|
157
|
+
|
171
158
|
describe "#unsubscribe" do
|
172
159
|
it "makes a DELETE to the subscription path" do
|
173
160
|
@updates.api.should_receive(:graph_call).with(@updates.subscription_path, anything, "delete", anything)
|
@@ -179,65 +166,76 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
179
166
|
@updates.api.should_receive(:graph_call).with(anything, hash_including(:object => obj), anything, anything)
|
180
167
|
@updates.unsubscribe(obj)
|
181
168
|
end
|
182
|
-
|
183
|
-
it "requests the status component" do
|
184
|
-
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(:http_component => :status))
|
185
|
-
@updates.unsubscribe("user")
|
186
|
-
end
|
187
|
-
|
169
|
+
|
188
170
|
it "accepts an options hash" do
|
189
171
|
options = {:a => 2, :b => "C"}
|
190
172
|
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
191
173
|
@updates.unsubscribe("user", options)
|
192
174
|
end
|
193
|
-
|
194
|
-
it "overrides any provided http_component" do
|
195
|
-
# since we test against status, we need to ensure that we get that
|
196
|
-
options = {:http_component => :body}
|
197
|
-
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(:http_component => :status))
|
198
|
-
@updates.unsubscribe("user", options)
|
199
|
-
end
|
200
|
-
|
175
|
+
|
201
176
|
describe "in practice" do
|
202
|
-
it "unsubscribes a valid individual object successfully" do
|
203
|
-
@updates.unsubscribe("user").
|
177
|
+
it "unsubscribes a valid individual object successfully" do
|
178
|
+
expect { @updates.unsubscribe("user") }.to_not raise_error
|
204
179
|
end
|
205
180
|
|
206
|
-
it "unsubscribes all subscriptions successfully" do
|
207
|
-
@updates.unsubscribe.
|
181
|
+
it "unsubscribes all subscriptions successfully" do
|
182
|
+
expect { @updates.unsubscribe }.to_not raise_error
|
208
183
|
end
|
209
184
|
|
210
|
-
it "fails when an invalid object is provided to unsubscribe" do
|
185
|
+
it "fails when an invalid object is provided to unsubscribe" do
|
211
186
|
expect { @updates.unsubscribe("kittens") }.to raise_error(Koala::Facebook::APIError)
|
212
187
|
end
|
213
188
|
end
|
214
189
|
end
|
215
|
-
|
190
|
+
|
216
191
|
describe "#list_subscriptions" do
|
217
192
|
it "GETs the subscription path" do
|
218
193
|
@updates.api.should_receive(:graph_call).with(@updates.subscription_path, anything, "get", anything)
|
219
194
|
@updates.list_subscriptions
|
220
195
|
end
|
221
|
-
|
196
|
+
|
222
197
|
it "accepts options" do
|
223
|
-
options = {:a => 3, :b => "D"}
|
198
|
+
options = {:a => 3, :b => "D"}
|
224
199
|
@updates.api.should_receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
225
200
|
@updates.list_subscriptions(options)
|
226
201
|
end
|
227
|
-
|
202
|
+
|
228
203
|
describe "in practice" do
|
229
204
|
it "lists subscriptions properly" do
|
230
205
|
@updates.list_subscriptions.should be_a(Array)
|
231
206
|
end
|
232
207
|
end
|
233
208
|
end
|
234
|
-
|
209
|
+
|
235
210
|
describe "#subscription_path" do
|
236
211
|
it "returns the app_id/subscriptions" do
|
237
212
|
@updates.subscription_path.should == "#{@app_id}/subscriptions"
|
238
213
|
end
|
239
214
|
end
|
240
|
-
|
215
|
+
|
216
|
+
describe ".validate_update" do
|
217
|
+
it "returns false if there is no X-Hub-Signature header" do
|
218
|
+
@updates.validate_update("", {}).should be_false
|
219
|
+
end
|
220
|
+
|
221
|
+
it "returns false if the signature doesn't match the body" do
|
222
|
+
@updates.validate_update("", {"X-Hub-Signature" => "sha1=badsha1"}).should be_false
|
223
|
+
end
|
224
|
+
|
225
|
+
it "results true if the signature matches the body with the secret" do
|
226
|
+
body = "BODY"
|
227
|
+
signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body).chomp
|
228
|
+
@updates.validate_update(body, {"X-Hub-Signature" => "sha1=#{signature}"}).should be_true
|
229
|
+
end
|
230
|
+
|
231
|
+
it "results true with alternate HTTP_X_HUB_SIGNATURE header" do
|
232
|
+
body = "BODY"
|
233
|
+
signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body).chomp
|
234
|
+
@updates.validate_update(body, {"HTTP_X_HUB_SIGNATURE" => "sha1=#{signature}"}).should be_true
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
241
239
|
describe ".meet_challenge" do
|
242
240
|
it "returns false if hub.mode isn't subscribe" do
|
243
241
|
params = {'hub.mode' => 'not subscribe'}
|
@@ -250,56 +248,56 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
250
248
|
Koala::Facebook::RealtimeUpdates.meet_challenge(params){|token| block_evaluated = true}
|
251
249
|
block_evaluated.should be_false
|
252
250
|
end
|
253
|
-
|
251
|
+
|
254
252
|
it "returns false if not given a verify_token or block" do
|
255
253
|
params = {'hub.mode' => 'subscribe'}
|
256
254
|
Koala::Facebook::RealtimeUpdates.meet_challenge(params).should be_false
|
257
255
|
end
|
258
|
-
|
256
|
+
|
259
257
|
describe "and mode is 'subscribe'" do
|
260
|
-
before(:each) do
|
258
|
+
before(:each) do
|
261
259
|
@params = {'hub.mode' => 'subscribe'}
|
262
260
|
end
|
263
|
-
|
261
|
+
|
264
262
|
describe "and a token is given" do
|
265
263
|
before(:each) do
|
266
264
|
@token = 'token'
|
267
265
|
@params['hub.verify_token'] = @token
|
268
266
|
end
|
269
|
-
|
267
|
+
|
270
268
|
it "returns false if the given verify token doesn't match" do
|
271
269
|
Koala::Facebook::RealtimeUpdates.meet_challenge(@params, @token + '1').should be_false
|
272
270
|
end
|
273
|
-
|
271
|
+
|
274
272
|
it "returns the challenge if the given verify token matches" do
|
275
273
|
@params['hub.challenge'] = 'challenge val'
|
276
274
|
Koala::Facebook::RealtimeUpdates.meet_challenge(@params, @token).should == @params['hub.challenge']
|
277
275
|
end
|
278
276
|
end
|
279
|
-
|
277
|
+
|
280
278
|
describe "and a block is given" do
|
281
279
|
before :each do
|
282
280
|
@params['hub.verify_token'] = @token
|
283
281
|
end
|
284
|
-
|
282
|
+
|
285
283
|
it "gives the block the token as a parameter" do
|
286
284
|
Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
287
285
|
token.should == @token
|
288
286
|
end
|
289
287
|
end
|
290
|
-
|
288
|
+
|
291
289
|
it "returns false if the given block return false" do
|
292
290
|
Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
293
291
|
false
|
294
292
|
end.should be_false
|
295
293
|
end
|
296
|
-
|
294
|
+
|
297
295
|
it "returns false if the given block returns nil" do
|
298
296
|
Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
299
297
|
nil
|
300
298
|
end.should be_false
|
301
299
|
end
|
302
|
-
|
300
|
+
|
303
301
|
it "returns the challenge if the given block returns true" do
|
304
302
|
@params['hub.challenge'] = 'challenge val'
|
305
303
|
Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|