Topic: Testing with cookies

I'm trying to test my "remember me" function.  It sets a cookie so that we someone comes back they are automatically logged in.  The problem is that it doesn't look the the cookie is saved when called from a functional test.  Look at this...

cookies[:auth_token] = { :value => valid_user.remember_token , :expires => valid_user.remember_token_expires }
puts "cookie in controller: " + cookies[:auth_token]

That's in the controller, and it errors out because cookies[:auth_token] is nil on the second line.

Has anyone already solved this problem?

Last edited by thabenksta (2006-07-19 13:53:04)

Re: Testing with cookies

This might help:
http://blog.teksol.info/articles/2006/0 … onal-tests

Railscasts - Free Ruby on Rails Screencasts

Re: Testing with cookies

Yeah, I saw that.  I tried using CGI::Cookie.new, but it still didn't work.  Plus, I'm setting the cookie in the controller, not the test, which is probably the problem.

Re: Testing with cookies

I see the problem now. The way cookies works is a Set-Cookie: line is added to the Header of the response when setting a cookie. The cookie isn't actually set until the browser gets the response. In other words, you can't retrieve a cookie right after you set it. You have to wait until the next request (which can be right after a redirect).

It is a little confusing how Rails does it because it looks like you are just setting a hash when setting a cookie, but Rails is doing some magic behind the scenes and just adding a line to the header of the response instead of setting the cookie hash.

If you want to test if a cookie is set, check out the @response.cookies in your test. That should contain a hash of the cookies which were set during the request.

Railscasts - Free Ruby on Rails Screencasts

Re: Testing with cookies

that does make sense, however the reason I was trying this is because The cookie wasn't being retained in the test.  Maybe it's something else that I'm missing, I'll look again. 

Thanks ryan, that helps.

Re: Testing with cookies

Aha, it was nil in the test because I was looking for cookies[:auth_token] instead of cookies["auth_token"].

Re: Testing with cookies

Have you tried it in an integration test? I'm not certain if that retains the cookies or not, but functional tests are designed to send one request per test. If you want to test how the action handles a cookie, set the cookie in the @request as shown in the link in my first reply.

It turns out that @response is unnecessary for requesting a cookie, you can get the cookie in the test by just doing "cookies['auth_token']".

Last edited by ryanb (2006-07-20 14:08:38)

Railscasts - Free Ruby on Rails Screencasts

Re: Testing with cookies

I haven't tried an integration test.  What I'm doing now is storing the cookie, and attempting to pass it along with the subsequent request.

    post :login, :user => @system.attributes, :save_login => '1'
    assert_response :redirect
    assert_redirected_to :controller => 'doodle', :action => 'index'
    assert_not_nil session[:current_user]
    assert_not_nil cookies['auth_token']
   
    cookie = cookies['auth_token']
   
    session[:current_user] = nil
   
    @controller = SystemController.new
    @request.cookies['auth_token'] = cookie
    get :index
    assert_not_nil session[:current_user]
    assert_response :redirect
    assert_redirected_to :controller => 'sites', :action => 'list'

but its not coming through, I tried many variations of line 12, including what was posted in that link.

Re: Testing with cookies

Hmm, I'd try placing it in a separate test.

def test_remember_me
  @request.cookies['auth_token'] = CGI::Cookie.new('auth_token', 'token_of_a_user')
  get :index
  assert_not_nil session[:current_user]
  assert_response :redirect
  assert_redirected_to :controller => 'sites', :action => 'list'
end

Railscasts - Free Ruby on Rails Screencasts

Re: Testing with cookies

Good call.

Lesson learned, multiple requests in a test makes things stupid.

Thanks mate.