Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails Pundit's current_user is nil in integration test

I'm using the gems pundit and devise. I have a delete link that only shows up if you are an admin. I have an integration test that I would like to verify that the delete link only shows up for admins.

test 'comment delete link shows when it should' do
  log_in_as @admin
  get movie_path(@movie)
  assert_select 'a[href=?]', movie_comment_path(comments(:one), @movie.id)
end

My test_helper.rb looks like this:

...
class ActiveSupport::TestCase
  ...
  def log_in_as(user, options = {})
    password = options[:password] || 'password'
    if integration_test?
      post user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
    else
      Devise::TestHelpers.sign_in user
    end
  end

  private

    # Returns true inside an integration test.
    def integration_test?
      defined?(post_via_redirect)
    end

end

The response.body looks all right, but indeed there is no delete link. There is one when I run the development server and visit the page myself. I've narrowed this down to the current_user that pundit uses in the policies is being passed in with a value of nil. This is my comment_policy.rb:

class CommentPolicy
  attr_reader :current_user, :comment

  def initialize(current_user, model)
    @current_user = current_user
    @comment      = model
  end

  def create?
    if @current_user
      @current_user.member? or @current_user.content_creator? or @current_user.moderator? or @current_user.admin?
    end
  end

  def destroy?
    if @current_user
      @current_user == @comment.user or @current_user.moderator? or @current_user.admin?
    end
  end

end

As a closing remark, I've heard that Rails 5 has opted for integration tests instead of controller tests as we know them from Rails 4 for the default type of tests to be generated for our controllers. If this is the case, devise would be a heck of a lot more useful out of the box when using Rails 5 if the sign_in/sign_out helpers that work in controller tests were made to work in integration tests as well. But would I still have this issue of pundit not knowing what current_user is? I'm assuming this all works fine in controller tests because the current_user is scoped to controllers? Any and all light shed on this topic is much appreciated, but I would really like to figure out how to get integration tests to work with this setup because I have about a billion I want to write right now.

like image 832
Jake Smith Avatar asked Mar 15 '16 01:03

Jake Smith


1 Answers

Not that it totally matters, but does it need to be using current_user in the policy or can it just use user in the policy. By this I mean according to the elabs/pundit README on Github I would just use @user and user everywhere instead of current_user. Read the README if I confused you.

Additionally the nil for current_user typically occurs when you don't have a valid CSRF token for your request. When you do this on the website manually by going to localhost:3000 or w/e you are first performing a get on the login path before doing the post on the login path with your credentials. In your integration test I don't seem to see where you are performing that get in order to get the CSRF for your session.

Hope this helps!!!

like image 168
Billy Ferguson Avatar answered Sep 28 '22 05:09

Billy Ferguson