Lee Edwards's blog



Lee EdwardsLee Edwards
Interacting with popup windows in Cucumber/Selenium
edit Posted by Lee Edwards on Monday October 24, 2011 at 09:00PM

OAuth providers like LinkedIn often pop-up in a new browser window rather than in Javascript so that the user entering their credentials can see the location bar to be sure they are not being phished by the website requesting their credentials. This is great for security, but not so great for Cucumber testing.

features/signup.feature

Scenario: Sign Up with LinkedIn
  When I go to the home page
  And I follow "Sign Up"
  And I grant LinkedIn access
  Then I should be on the new user page

My application has a hyperlink that opens the OAuth login on the OAuth provider's website in a new window. Let's presume the simple matter of wiring this up is already coded in my view.

Testing this with Cucumber requires telling the Selenium web driver to interact with the new popup window. We can do this using page.driver.browser.window_handles to find the newest window handle and scoping out actions to that window.

features/support/signup_steps.rb

When /^I grant LinkedIn access$/ do
  begin
    main, popup = page.driver.browser.window_handles
    within_window(popup) do
      fill_in("Email", :with => "newlee@pivotallabs.com")
      fill_in("Password", :with => "password")
      click_on("Ok, I'll Allow It")
    end
  rescue
  end
end

And that's it!

Keep in mind that if you use this test as-is, you will be hitting LinkedIn on the real Internet. This is great if you want a test that will always verify the real API, but not so good for CI, since it is Internet connection-dependent and slow. Consider using something like VCR or Artifice to stub out your service calls.

Lee EdwardsLee Edwards
Visit to Olin College
edit Posted by Lee Edwards on Thursday February 03, 2011 at 07:01PM

Visiting Olin

Today, Josh Knowles, Grant Hutchins, and I visited Franklin W. Olin College of Engineering in Needham, MA to talk to Prof. Mark L. Chang's amazing new dotcom course. We talked about agile development, and more specifically how Pivotal does agile and why. We went through an example of test-driven development for a simple Rails app, and had a miniature inception for a fictitious product.

Some students asked for some resources, particularly for documentation, so I put together a collection of resources for anyone looking to pick up agile, TDD and Ruby on Rails. This is intentionally not an exhaustive list. I wanted to include the bare minimum for getting started on each topic as a jumping off point and include further references at the end.

Lee EdwardsLee Edwards
HTTP Basic Authentication and Devise
edit Posted by Lee Edwards on Wednesday January 26, 2011 at 09:48AM

Say you're using Heroku to host a staging version of your app that uses Devise for authentication. You want to keep unwanted visitors out of your staging app, but your app only uses authentication for certain features. You want to block outsiders from accessing the app entirely. Since Heroku doesn't allow you whitelist IP addresses in your webserver config, you might want to try HTTP basic access authentication to provide top-level authentication. Doing this in Rails is pretty straightforward. Let's assume your staging app runs in the "staging environment."

application_controller.rb:

before_filter :authenticate if Rails.env.staging?

protected

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
    end
end

See Ryan Bates' Railscast #82 HTTP Basic Authentication for more info.

This will work for most cases. However, since we have Devise installed, this won't work. Devise will enter an infinite loop of redirects unless we tell Warden to set the performed flag.

application_controller.rb:

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
    end
    warden.custom_failure! if performed?
end

But wait, we're still not done. Devise has the ability to use your HTTP Basic Authentication credentials and use it to log into its own authentication system - a cool feature if you want to be able to pass your login credentials over HTTP, perhaps as a simple way to authenticate an API consumer. However, in our case, we want to keep the HTTP Basic Authentication that we require for the entire site separate from the Devise login that we use internal to the app, so we need to disable Devise's ability to capture our HTTP Basic Authentication credentials. In some versions of Devise, this feature is on by default, and in others it is off by default. Check your devise.rb file and make sure you have uncommented the line that disables Devise's http_authenticatable configuration setting.

devise.rb:

config.http_authenticatable = false

Be warned that HTTP Basic Authentication transmits the username and password in clear text, so you should not use this method for applications where a higher level of security is required.