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