Topic: login_as not assigning the proper role in my functional test

I'm looking at adding some authentication to my application - since I've never really worked with it before, and want to take advantage of the Rails community, I'm using the restful_authentication plugin, and following the tutorial posted here on the forum: http://www.railsforum.com/viewtopic.php?id=14216

Since I also want to start experimenting with unit tests (I have never really used them in my prior 'life' as a .NET developer), I'm making sure my tests run before I add my own functionality.  However, the first functional test fails with the following error:

test_should_get_index(RolesControllerTest)
method test_should_get_index in roles_controller_test.rb at line 15
method run in default.rb at line 7
Expected response to be a <:success>, but was <302>

Now, in my RolesController I specify a before_filter requiring the logged-in user to be a member of the administrators group (this was taken verbatim from the Tutorial).

In app/models/user.rb:

  has_many :permissions
  has_many :roles, :through => :permissions

In app/models/role.rb:

  has_many :permissions
  has_many :users, :through => :permissions

In app/models/permission.rb:

  belongs_to :user
  belongs_to :role

My roles.yml file looks like this:

admin_role:
  name: administrator

and my permissions.yml file looks like this:

admin:
    user: quentin # quentin is the first user provided by restful_authentication in users.yml
    role: admin_role

Finally, in test/functional/roles_controller_test.rb

class RolesControllerTest < ActionController::TestCase
  fixtures :users, :roles, :permissions
 
  def setup
    @controller = RolesController.new
    @request = ActionController::TestRequest.new
    @response = ActionController::TestResponse.new
    login_as :quentin
  end
 
  def test_should_get_index
    get :index
    assert_response :success
    assert_not_nil assigns(:roles)
  end

I have verified that the user 'quentin' has the administrator permission, but for some reason login_as isn't doing something properly, as it's still redirecting (302 is a redirect, right?) instead of getting the proper page.  Interestingly enough, if I put login_as :quentin inside of the method itself, ActiveRecord fails with the error that it can't find a User without an ID - I thought that a yml fixture didn't need an explicit ID as of Rails 2.0.  It fails if I explicitly say id: 1, as well.  I'm really at a loss for why it's failing.

Could anyone point me in the right direction?  I'm not really used to Rails and Ruby yet, but I want to learn - it's much more pleasant than using C#, if I do say so myself.

Last edited by wayne.m (2008-03-17 22:23:08)

Wayne M.

Re: login_as not assigning the proper role in my functional test

I did some more digging, and the problem seems to be that it's not assigning the role (users(:quentin).roles comes up as nil).  I'm not sure where the problem lies, then.

Also I noticed that it not finding the ID was coming up only when I froze rails; I unfroze (thawed?) it and now it's at least picking up the user "quentin", although still not the permissions.  Any idea why that would be?  I thought freezing your rails was a good idea for a site; should I not be doing that when I create a new application, and only when I'm ready to deploy it?

Still hoping someone can shed some light on this - I plan to look around even more when I'm home from work.

Wayne M.

Re: login_as not assigning the proper role in my functional test

I'm having this exact same problem (trying to test a controller that requires users to be logged in), and my tests keep failing because instead of assert_response :success is actually a redirect.

Did you ever figure this out?

Re: login_as not assigning the proper role in my functional test

Has anyone ever found a solution to this yet? I'm stuck in the same boat as you guys...

Thanks

Re: login_as not assigning the proper role in my functional test

im stuck here too. I tried including the AuthenticatedTestHelper in the bottom of my test_helper.rb file then use login_as in my functional tests but it still didnt work...

I am wondering if I have to require the sessions_controller some how so it can process the request...

Last edited by saltzmanjoelh (2008-09-11 15:28:33)

Re: login_as not assigning the proper role in my functional test

turns out it was simple. It was just the way I was trying to pass in my variables, params, and session variables.

get :new, {:some_param => "info" }, { :user_id => 2 }

The third set is where I pass in my user_id session variable.

Re: login_as not assigning the proper role in my functional test

I don't know if you guys have the problem solved, but I seem to remember I had the same a while ago. Turned out it had to do with the way my fixtures were loaded and the fact you are using direct references to other fixtures for your has_many declarations. So when you declare your 'admin' permission, it supposes there is already a fixture 'quentin' (a user) and a fixture 'admin_role' (a role).

However, the fixtures are loaded in alphabetical order, so permissions before users and roles. That's why the 'admin' permission is not set properly.

What I did was to add a line to my 'environment.db':

# environment.rb
# Load fixtures for testing in correct order to preserve parent-child relationships
  ENV['FIXTURES'] ||= 'parent,child'

This should load your fixtures in the correct order.

Not sure this will help your issue, it's a while ago I added this line to all my projects.

Last edited by dgroten (2008-09-22 08:47:22)

Re: login_as not assigning the proper role in my functional test

I have tried changing the environment file as you said but that has not worked either.
I do not have the 'permissions' model in my app but I do have a roles_users join table.

#lib/authenticated_system.rb

def check_role(role)
      unless logged_in? && current_user.has_role?(role)
        flash[:error]="Sorry you do not have permission to do that"
        redirect_to login_path
      end
    end
   
    def check_administrator_role
      check_role('Admin')
    end
   
    def check_editor_role
      check_role('Editor')
    end
   
    def check_moderator_role
      check_role('Moderator')
    end

#user.rb
has_and_belongs_to_many :roles

#role.rb
has_and_belongs_to_many :users

#roles_users.yml
admin:
    role_id: 1
    user_id: 1

editor:
    role_id: 2
    user_id: 2
   
moderator:
    role_id: 3
    user_id: 3


#users.yml
admin_user:
  #id: 1
  login: admin
  email: admin@test.com
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # clear password = test
  created_at: <%= 1.days.ago.to_s :db %>
  #activation_code: 8f24789ae988411ccf33ab0c30fe9106fab32e9b
  activated_at: <%= 1.days.ago.to_s :db %>
  posts_count: 0

editor_user:
  #id: 2
  login: ryan
  email: editor@test.com
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # clear password = test
  created_at: <%= 1.days.ago.to_s :db %>
  #activation_code: 8f24789ae988411ccf33ab0c30fe9106fab32e9a
  activated_at: <%= 1.days.ago.to_s :db %>
  posts_count: 0
 
moderator_user:
  #id: 3
  login: david
  email: moderator@test.com
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # clear password = test
  created_at: <%= 1.days.ago.to_s :db %>
  #activation_code: 8f24789ae988411ccf33ab0c30fe9106fab32e9a
  activated_at: <%= 1.days.ago.to_s :db %>
  posts_count: 0


#roles.yml
admin:
  id: 1
  name: Admin
editor:
  id: 2
  name: Editor
moderator:
  id: 3
  name: Moderator

#pages_controller_test.rb
class PagesControllerTest < ActionController::TestCase
  fixtures :pages, :users, :roles, :roles_users
 
  def setup
    @controller = PagesController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end
 
  def test_should_get_new
    login_as(:editor_user) #this should log the editor user in
    get :new
    assert_response :success
  end
 
  def test_should_not_get_new
    get :new
    assert_redirected_to login_path
  end
 
  def test_should_not_create_page
    assert_difference('Page.count', 0) do
      post :create, :page => { :title => "Test title page", :body => "Does not create page" }
    end
  end

  def test_should_not_get_edit
    get :edit, :id => pages(:valid_page).id
    assert_redirected_to login_path
  end

  def test_should_not_update_page
    put :update, :id => pages(:valid_page).id, :page => {:title => "this is the new page title"}
    assert_redirected_to login_path
  end

  def test_should_not_destroy_page
    assert_difference('Page.count', 0) do
      delete :destroy, :id => pages(:valid_page).id
    end
    assert_redirected_to login_path
  end
 
end

Last edited by Zappa (2008-09-22 15:23:19)

Re: login_as not assigning the proper role in my functional test

Why are the id's of your users commented out in the fixture file? Since you are explicitely referencing them to assign roles, you must make sure the ids are correct. Check your test database to see if the fixtures are properly defined in the database with correct ids.

Re: login_as not assigning the proper role in my functional test

you don't need to specify the ids (nor the join models). 

See ryanb's (short) railscast on the topic:
http://railscasts.com/episodes/81-fixtures-in-rails-2-0

Re: login_as not assigning the proper role in my functional test

I was having a bizarre problem that this thread helped me to track down... maybe it will be useful to someone else. Thx to @dgroten for the lead.

I'm using the restful_authentication and role_requirement plugins. I had a functional test case that was calling "login_as :admin" and performing actions that required the admin role. When I ran this test alone it worked gloriously. But when I ran it together with other functional tests, it failed because the admin user didn't have the admin role.

From this thread I got the idea to look at the fixtures. I discovered that I was calling "fixtures :users, :roles, :roles_users", when I should just be calling "fixtures :users". Changing that, everything works perfectly again. I still don't understand the mechanism that would make it break like that, but what the heck.