views:

1158

answers:

3

Hi! I'm writing Cucumber tests for a Sinatra based application using Webrat. For some tests I need to implement a scenario like

Given I am logged in as admin
When I am visiting "/"
Then I should see "Settings"

I define steps like this:

Given /^I am logged in as "(.+)"$/ do |user|
    visit "/login"
    fill_in "login", :with => user
    fill_in "password", :with => "123456"
    click_button "Login"
end

When /^I am viewing "(.+)"$/ do |url|
    visit(url)
end

Then /^I should see "(.+)"$/ do |text|
    response_body.should =~ /#{text}/
end

On success a cookie is created

response.set_cookie(cookie_name, coockie_value)

and then verified in views when user tries to access admin pages via helper method:

def logged_in?
    request.cookies[cookie_name] == cookie_value
end

And it looks like Webrat doesn't store cookies. Tests don't report any error, but "logged_in?" in views is always false, like the cookie was not saved.

Am I doing something wrong? If this is just how Webrat works, what is the best workaround?

A: 

The workaround is use Webrat with Selenium back end. It runs all tests in a separate Firefox window, so cookies or javascript is not a problem. The downside is extra time and resources required to run Firefox and do all the real clicks, rendering etc.

A: 

You could have your "Given /^I am logged in" step hack logged_in?:

Given /^I am logged in as "(.+)"$/ do |user|
    visit "/login"
    fill_in "login", :with => user
    fill_in "password", :with => "123456"
    click_button "Login"

    ApplicationController.class_eval <<-EOE
      def current_user
        @current_user ||= User.find_by_name(#{EOE})
      end
    end
EOE
end

There are two downsides:

  1. It's really hackish to mix view-level and controller-level issues like this.
  2. It'll be difficult to mock up "logout"
James A. Rosen
This didn't work for me
davetron5000
+1  A: 

The real problem is the way Sinatra is treating sessions in the test environment. Search the Google group for the discussion, but the real solution is to simply use:

use Rack::Session::Cookie

and not

enable :sessions

Using Selenium is nice but it's overkill as a solution for the OP's problem.

djanowski