Forum: RSpec Restful Authentication and Cucumber

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Andrei E. (Guest)
on 2008-11-27 08:19
(Received via mailing list)
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-...

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
David C. (Guest)
on 2008-11-27 13:32
(Received via mailing list)
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
Andrei E. (Guest)
on 2008-11-27 15:51
(Received via mailing list)
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
Michael G. (Guest)
on 2008-11-28 01:38
(Received via mailing list)
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.
Matt W. (Guest)
on 2008-11-28 13:17
(Received via mailing list)
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
Alberto P. (Guest)
on 2008-12-09 01:38
(Received via mailing list)
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.
This topic is locked and can not be replied to.