Ruby Browser Hooks & Facebook Integration Testing
Why don't you subscribe to my blog while you're here? I'm a freelance web developer and I blog about Ruby, Rails, and business online.
Go ahead and subscribe to my RSS feed. Thanks for visiting!
Recently I had to write some integration tests to ensure that my Facebook application was communicating with Facebook correctly. I started out trying to use plain old Net::HTTP which was painful because Facebook appears to actively block programmatic access through their login page. Just as I was about to give up I discovered a suite of libraries that allow you to access your browser from Ruby! The library is fantastic as I can very simply control the forms and content in my browser, straight from my Ruby code. Nice!
The library is called Watir. Watir is a tool to hook in Ruby with IE, but there are ports for Safari and Firefox. I ended up going with the Safari port as the Firefox port looked a bit tricky to install.
Now, for the pièce de résistance …
require File.dirname(__FILE__) + '/../spec_helper'
require 'rubygems'
require 'safariwatir'
describe UserController do
FB_EMAIL = 'xxx@xxxxx.com'
FB_PASS = 'xxxxx'
FB_URL = 'http://www.facebook.com'
CALLBACK_URL = 'http://dev.xxxxxxxxx.com'
FB_APP_URL = 'http://apps.facebook.com/xxxxx/'
FB_LOGOUT_URL = 'http://www.facebook.com/logout.php'
LOGOUT_REGEX = /http:\/\/www.facebook.com\/logout.php\?.+/
it "should use UserController" do
controller.should be_an_instance_of(UserController)
end
describe "POST 'index'" do
before(:each) do
@browser = Watir::Safari.new
@browser.set_fast_speed
@browser.goto(FB_APP_URL)
@browser.link(:url, LOGOUT_REGEX).click rescue nil
end
it "should find authentication prompt" do
@browser.goto(FB_APP_URL)
@browser.form(:id, 'loginform').exist?.should_not == nil
expected = 'Login to Facebook to enjoy the full functionality of'
@browser.contains_text(expected).should > 0
end
it "should authenticate" do
authenticate
expected = /Login to the .* application?/
@browser.contains_text(expected).should != nil
end
it "should log in to the application" do
authenticate
@browser.form(:index, 1).submit
end
end
private
def authenticate
@browser.goto(FB_APP_URL)
@browser.text_field(:id, 'email').set(FB_EMAIL)
@browser.password(:name, 'pass').set(FB_PASS)
@browser.form(:index, 1).submit
end
end
The code above is a work in progress, but it is still fully functional rspec code. Feel free to use it.
Just a note if you do end up using the Safari Watir port. I had to make a change to the core libraries as there seemed to be a race condition. If you are affected, you will notice an exception thrown part way through entering the data in a form. My quick fix/hack is to extend the sleep time from 1 to something larger. I had no problems after increasing the sleep time to 4.
# safariwatir/scripter.rb def page_load yield #sleep 1 sleep 4 .... end

