Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access the current user in Cucumber features - Devise

Note: I am very new to Cucumber.

I am trying to make a generalized step (not sure if one already exists somewhere or not) so that you can easily add objects to another object, given the association exists. I want to do something like:

manage_notes.feature

Background: Login User
  Given the following user records
    | email          | password |
    | [email protected] | password |
  Given I am logged in as "[email protected]" with password "password"

Scenario: Edit existing note
  Given I have already created a note that belongs to current_user

general_steps.rb

Given /^the following (.+) records?$/ do |factory, table|
  table.hashes.each do |hash|
    Factory(factory, hash)
  end
end

Given /^I am logged in as "([^\"]*)" with password "([^\"]*)"$/ do |email, password|
  unless email.blank?
    visit new_user_session_path
    fill_in "Email", :with => email
    fill_in "Password", :with => password
    click_button "Sign In"
  end
end

note_steps.rb

  Given /^I have already created a (.+) that belongs to (.+)$/ do |factory, resource|
      model = Factory(factory)
      resource.send(model.class.to_s.downcase.pluralize) << model
  end

Seems like there might be a way to use the devise 'current_user' helper.

What is the correct way to accessing the user that is logged in?

Please let me know if you need more information. Thanks!

UPDATE 1: I have temporarily fixed my issue by creating a new step that allows me to do:

Given I have already created a note that is owned by the user with email "[email protected]"

But I don't want to specify the email, I'd still like to be able to use the logged in user if possible.

UPDATE 2: Added general_steps.rb

So you can see, that in my 'Background', the user is created via a Factory, and then is logged in via my interface. I want to access the model of that logged in User.

like image 500
ardavis Avatar asked Jun 10 '11 12:06

ardavis


3 Answers

I don't use Devise, so I can't answer specifically to if Devise has method of access the current_user.

But I actually like to use Pickle to help me keep my references. And perhaps this can help you out till you find a more Devise specific way to achieve what you want.

Given /^the following (.+) records$/ do |factory, table|
  table.hashes.each do |hash|
    Factory(factory, hash)

    # since this is like an all encompassing factory creator, this line to 
    # create a Pickle references might need a bit more extra work if you want
    # to create references for other factory types

    # I assume email is unique, else use a unique identifier of some sort
    find_model! %{user: "#{hash['email']}"}, {:email => hash['email']} 
  end
end

Given /^I have already created a (.+) that belongs to #{capture_model}$/ do |factory, name|
  model = Factory(factory)
  ref = model!(name) # we find that reference here
  ref.send(model.class.to_s.downcase.pluralize) << model
end

This would read

Given I have already created a note that belongs to user: "[email protected]"

# I would just change this to 
Given I have already created a note

# or
Given a note was created for user: "[email protected]"

You are I since you said Given I logged in..., no need to say that belongs to user: "[email protected]" it's already you.

Not to mention it could lead to confusion when you read it, some people may think you are adding a note to a user, who they might now know (or realize) is actually yourself.


While you still have to reference explicitly (eg. user: "John Doe"), I think that is a plus. By always calling specific references, everyone knows who is being referenced and there is no question about who is doing what to what.

Pickle serves us very well for this purpose. The only problematic areas we find are with things created directly through the app's ui, which gets a bit tricky to ensure you are creating the right reference to it.

Pickle has a large number of uses so definitely take a look.


Upate

You will have to find yourself here. Since, like you wanted, there is no current_user option (as far as we know). So you basically have to go find the "actor" in this scenario.

Given /^I have already created a note$/ do
  user = model!(%{user: "[email protected]"}) # if using pickle
  # user = User.find_by_email("[email protected]") # if just regular AR
  user.notes << Note.create
end
like image 118
nowk Avatar answered Oct 13 '22 21:10

nowk


I just solve it very simple: I have "FactoryGirl" user defined, then this method...

Given(/^I am users logged in as "(.*?)" with password "(.*?)"$/) do |email, pass|
  visit new_user_session_path
  fill_in "user_email", :with => email
  fill_in "user_password", :with => pass
  click_button I18n.t("login.sign_in")
  @current_user = User.find_by_email(email)
end

further on You could use @current_user in Your steps

like image 31
lukapiske Avatar answered Oct 13 '22 21:10

lukapiske


This topic is quite old, but here is the solution I use. You must load this module, in env.rb, for example. Using it you can access the current user using either @current_user or current_user in your steps.

module UserSessionHelper
  def current_user
    @current_user
  end

  def login(user=nil)
    if user.nil?
      @current_user = FactoryGirl.create(:user, username: fake_name)
    else
      @current_user = user
    end
    visit login_path
    fill_in 'Username', with: @current_user.username
    fill_in 'Password', with: '1234'
    click_button 'Login'
    page.should have_content('Logout')
  end

  def logout
    click_link 'Logout'
  end
end

RSpec.configure do |config|
  config.include UserSessionHelper
end if RSpec.respond_to?(:configure)

World(UserSessionHelper) if respond_to?(:World)
like image 23
Kadu Diógenes Avatar answered Oct 13 '22 20:10

Kadu Diógenes