DRY act_as_authenticated functional testing

You can either put the login_as in the setup method or have tests that capture the behavior of not being logged in separately from the behavior when the current user is already known. If you have some authorization process (what a user is allowed to do) separate from the authentication process (who is this user), then you may want to go that route since you have three conditions: not authenticated (i.e., not logged in); authenticated, but unauthorized (e.g., normal user accessing a privileged action); and authenticated and authorized. (Note that someone can be authorized to do something even when not authenticated such as signing up or seeing the login form.)

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

Rob Biedenharn wrote:

You can either put the login_as in the setup method or have tests that capture the behavior of not being logged in separately from the behavior when the current user is already known. If you have some authorization process (what a user is allowed to do) separate from the authentication process (who is this user), then you may want to go that route since you have three conditions: not authenticated (i.e., not logged in); authenticated, but unauthorized (e.g., normal user accessing a privileged action); and authenticated and authorized. (Note that someone can be authorized to do something even when not authenticated such as signing up or seeing the login form.)

Hi Rob -

Thanks for your help. I do have the authorization and authentication processes separate from one another. I have:

def setup    login_as :quentin end

But now the only way that I'm able to get this to work is if I include this as the first line for all of my tests.

assert login_as("quentin")

If that assert line is missing, then my response changes from (:success) to (302) - redirect.

Thanks!

UPDATE:

Actually, I can comment out the def setup and as long as I leave in assert login_as in each test, the tests pass. Something doesn't seem right.

You ought to have a bit more in your setup than that for a functional test.

When I want to test both things, I have something like this (with 'foo' and 'bar' standing in for the application specific terms):

   def test_foo_selection_on_restricted_bar      login_as :regular      get :foos, :id => 9      assert_redirected_to bar_url    end

   def test_foo_selection_needs_login      get :foos, :id => 1      assert_response :redirect    end

   def test_foo_selection      login_as :admin      get :foos, :id => 1      assert_response :success    end

When I just want to be logged in for every test, the setup looks like:

   def setup      @controller = FoosController.new      @request = ActionController::TestRequest.new      @response = ActionController::TestResponse.new      login_as :admin    end

It's also possible that you have two definitions for setup and only the last one is really having any effect (since its definition would have overwritten the original one).

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

Rob Biedenharn wrote:

You ought to have a bit more in your setup than that for a functional test.

The tests are actually testing other controller functions, not the login function. But I do have login tests. Is it possible to have the def setup with the login_as :admin and also have tests that test the login.

For example I would want Test 1 - tests the login, Test 2 - tests the controller function that needs the login.

If I have def setup with the login, will Test 1 then be useless or can I set the login user to nil or something like that?

Thanks for all of your help!

The definition of login_as is in:   lib/authenticated_test_helper.rb

You get the effect of logging out with:   login_as nil

It can be immensely helpful to read the Ruby code that implements this kind of thing. One reason is to see the answer to this kind of question directly, but also you start to see how easy some of the "magic" really is and start to craft some of your own.

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

I am also having a problem running functional tests and putting the login_as in the setup method. I am on Rails 2.0.2 and trying to use:

def setup   super   login_as :dan end

This does not work. In the controller being tested, current_user is equal to :false.

However, if I put the login_as directly into each functional test method, it works.

Anybody know why?

-Shannon

I have implemented this:

def setup   login_as :quentin end

  def test_should_get_new     get :new     assert_response :success   end

And get this error: Expected response to be a <:success>, but was <302>

If I have the test as this it passes.   def test_should_get_new     assert login_as :quentin     get :new     assert_response :success   end

Sorry, I meant to write that I have this as def setup. I had copied and pasted old code. Foos is replaced by name controller name

def setup      @controller = FoosController.new      @request = ActionController::TestRequest.new      @response = ActionController::TestResponse.new      login_as :admin    end