Apologies for not chaning the subject line. :(
Hi all,
I wanted to test requests from internal facebook apps, so I''ve been
mimicking FBML requests from facebook in my tests using the following:
def test_can_facebook_internal_app_login
fb_login_as :facebooker
num_of_members = Member.count
facebook_request :get, :home
assert_response :success
assert_equal num_of_members, Member.count
assert_session_user_data_exists
end
The code is fairly simple:
module Facebooker
module Rails
module TestHelpers
# user facebook id for facebook_request
def set_user_facebook_id(fb_id)
@fb_id = fb_id
end
# makes a request as if it was from facebook. Need to
set_user_facebook_id() first
# so it knows whom to send the request as.
def facebook_request(http_verb, action, params = { })
fb_params = { "fb_sig_time" => Time.now.to_f,
"fb_sig_locale" => "en_US",
"fb_sig_session_key" =>
"d82ebe8648254d4cef7d993a-1953401",
"fb_sig_position_fix" => "1",
"fb_sig_in_canvas" => "1",
"fb_sig_request_method" => http_verb.to_s.upcase,
"fb_sig_expires" => "0",
"fb_sig_added" => "1",
"fb_sig_api_key" => Facebooker::Session.api_key,
"fb_sig_profile_update_time" => "1203267404",
"fb_sig_user" => @fb_id }
fb_params.merge!("fb_sig" => signature_for(fb_params))
@request.accept = "text/fbml"
send(http_verb, action, params.merge(fb_params))
@request.accept = "text/html"
end
private
# TODO this is copied from session.rb MUST REFACTOR
def signature_for(params)
facebook_sig_params = params.inject({}) do |collection, pair|
collection[pair.first.sub(/^fb_sig_/, '''')] =
pair.last if
pair.first[0,7] == ''fb_sig_''
collection
end
raw_string = facebook_sig_params.map{ |*args|
args.join(''='') }.sort.join
actual_sig = Digest::MD5.hexdigest([raw_string,
Facebooker::Session.secret_key].join)
Digest::MD5.hexdigest([raw_string, Facebooker::Session.secret_key].join)
end
end
end
end
I had wanted to submit the code as a patch, but, there are two or
three glaring flaws with the code:
1) signature_for is duplicated here, because it''s a private/protected
method in Facebooker::Session. Would it be a bad idea to call
send(:singature_for) to call the protected method? Or is there
another way around it?
2) One has to call set_user_facebook_id in the setup of your tests in
order for facebook_request to work.
3) fb_sig_session_key expires over time, and I have to get another one
from a real facebook request. This is tedious. Is there a way to
generate a session key, or request a new one from facebook while
you''re in the unit tests?
I was wondering if anyone had good opinions or solutions to this, so
that they can be generic enough and clean enough for others to use.
Thanks.