Restful Authentication and Cucumber


#1

Hello,

I am using Restful Authentication and I would like to login in Cucumber.
I
am having trouble keeping the user logged in. I tried finding a solution
for
this everywhere. Only source is this article:
http://afreshcup.com/2008/10/09/authentication-in-cucumber-tests/

This is how my feature looks like:

Scenario: Register new place
Given I am logged in as a user
And I am on the new place page with parent place “Georgia”
When I fill in “Name” with “Atlanta”
And I press “Create”
And I should see “Atlanta”

This is the step:

Given /I am logged in as a user/ do
@current_user = Factory.define :user do |u|
u.name ‘the user’
u.email ‘removed_email_address@domain.invalid’
u.login ‘the_login’
u.password ‘password’
u.password_confirmation ‘password’
end
visits “/login”
fills_in(“login”, :with => “the_login”)
fills_in(“password”, :with => “password”)
clicks_button(“Log in”)
end

places controller

before_filter :login_required, :only => [:create]

GET /places/new

def new
@place = @parent_place.children.create

respond_to do |format|
  format.html # new.html.erb
end

end

POST /places

def create
@place = @parent_place.children.create(params[:place])

respond_to do |format|
  if @place.save
    flash[:notice] = 'Place was successfully created.'
    format.html { redirect_to(@place) }
  else
    format.html { render :action => "new" }
  end
end

end

The “Given I am logged in as a user” step passes, along with all the
steps,
except the last one (And I should see “Atlanta”). The problem is that
the
login page is shown and not the show page with the new place created.

What do I have to set in Cucumber so that it acts as if the user is
logged
in? In know that in Rspec :login_required should return true. What’s the
equivalent of that in Cucumber?

Thank you


#2

On Wed, Nov 26, 2008 at 11:58 PM, Andrei E. removed_email_address@domain.invalid
wrote:

Given I am logged in as a user
 u.email 'removed_email_address@domain.invalid'

places controller

end
format.html { render :action => “new” }
equivalent of that in Cucumber?
I’m not sure what you mean by “in RSpec :login_required should return
true,” but that might be a subject for a different thread.

When using Cucumber with Rails you’re dealing with a wrapped rails
integration test. Because integration tests (in rails) are designed to
support multiple user sessions within a single test (scenario in the
case of Cucumber), you don’t have any direct access to the internals
of any controllers.

With that, the problem you are having seems to be that the login step
is not actually working. Just because the step turns green doesn’t
mean the User is actually logged in. There are no expectations being
set that would fail, and it’s possible that the Factory.define method
doesn’t raise errors if it doesn’t actually create the User (I’m
guessing you’re using Factory Girl, but I have no experience with it
myself yet).

To debug this, I’d add an expectation to the Given step about
something on the page. When someone logs in, does the page say
something like “Welcome, the user”? If so, you can expect that text to
be there.

Also, check to make sure that the “the user” User is actually in the
database. Something like User.find_by_name(“the user”).should_not
be_nil.

HTH,
David


#3

David,

Thank you for your great insight. You’re assumptions were correct and
the
user wasn’t getting logged in, because I didn’t add all the necessary
paramenters for the user to be able to log in.
I am checking if the user is being created and also if after login,
there is
a message posted, such as Logged in. I posted that message in
Application
layout.

This is my working login step for anybody that might have a use for this
later on.

Given /I am logged in as a user/ do
@current_user = User.create!(
:name => ‘quentin’,
:email => ‘removed_email_address@domain.invalid’,
:login => ‘loginz’,
:password => ‘monkey’,
:password_confirmation => ‘monkey’,
:activated_at => ‘2008-11-22 12:13:59’,
:activation_code => nil,
:salt => ‘356a192b7913b04c54574d18c28d46e6395428ab’,
:crypted_password => ‘df42adbd0b4f7d31af495bcd170d4496686aecb1’,
:created_at => ‘2008-11-22 12:13:59’)

visits “/login”
fills_in(“login”, :with => “quentin”)
fills_in(“password”, :with => “monkey”)
clicks_button(“Log in”)
User.find_by_name(“quentin”).should_not be_nil
response.body.should =~ /Logged/m
end


#4

On Thu, Nov 27, 2008 at 12:58 AM, Andrei E. removed_email_address@domain.invalid
wrote:

Given I am logged in as a user
 u.email 'removed_email_address@domain.invalid'
 u.login  'the_login'
 u.password 'password'
 u.password_confirmation 'password'

end
visits “/login”
fills_in(“login”, :with => “the_login”)
fills_in(“password”, :with => “password”)
clicks_button(“Log in”)
end

I don’t think Factory.define returns the instance that you defined and
defining the factory certainly does not store the instance to the
database.

I’d recommend putting your factories in a separate file and require
them at the beginning of your step file.

You could then do @current_user = Factory(:user), which will actually
store the user to the database.

HTH,
Michael G.


#5

Hi Andrei,

visits “/login”
fills_in(“login”, :with => “the_login”)
fills_in(“password”, :with => “password”)
clicks_button(“Log in”)
end

you can simplify the code to activate the user.
This is my step definition for login:

When /^i login$/ do
user = Factory(:user)
user.register!
user.activate!
fill_in(“username”, :with => user.login)
fill_in(“password”, :with => user.password)
click_button(“Login”)
end

This is my factory code in test/factories.rb

Factory.define :user do |u|
u.login ‘user’
u.password ‘password’
u.password_confirmation ‘password’
u.email ‘removed_email_address@domain.invalid’
end

I think i saw a fork of factory_girl somewhere that supported before
and after hooks so you could actually call the register and activate
methods after save from within the factory definition code. This way
your steps and other tests would be much cleaner. I will look further
into it.

Cheers,
Alberto.


#6

On 27 Nov 2008, at 23:38, Michael G. wrote:

fills_in(“password”, :with => “password”)
clicks_button(“Log in”)
end

I don’t think Factory.define returns the instance that you defined and
defining the factory certainly does not store the instance to the
database.

I’d recommend putting your factories in a separate file and require
them at the beginning of your step file.

+1!!

That’s the whole point of the factory_girl - re-usable test data!

Once you’ve got that set up, a whole new world opens up.

For example, at Songkick, we have a step like this:

 Given /there is (?:one|an?) ([^ ]+)$/ do |entity_type|
   Factory(entity_type.underscore.to_sym)
 end

cheers,
Matt