Wilhelm Chung
2008-Mar-11 19:03 UTC
[Facebooker-talk] Facebooker-talk Digest, Vol 5, Issue 12
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.