Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test cookies.permanent.signed in Rails 3

I have a action in some controller that set some value in a permanent signed cookie like this:


def some_action
    cookies.permanent.signed[:cookie_name] = "somevalue"
end

And in some functional test, I'm trying to test if the cookie was set correctly suing this:


test "test cookies" do
    assert_equal "somevalue", cookies.permanent.signed[:cookie_name]
end


However, when I run the test, I got the following error:


NoMethodError: undefined method `permanent' for #

If I try only:


test "test cookies" do
    assert_equal "somevalue", cookies.signed[:cookie_name]
end


I get:


NoMethodError: undefined method `signed' for #

How to test signed cookies in Rails 3?

like image 884
Joao Pereira Avatar asked Feb 12 '11 18:02

Joao Pereira


3 Answers

I came across this question while Googling for a solution to a similar issue, so I'll post here. I was hoping to set a signed cookie in Rspec before testing a controller action. The following worked:

jar = ActionDispatch::Cookies::CookieJar.build(@request)
jar.signed[:some_key] = "some value"
@request.cookies['some_key'] = jar[:some_key]
get :show ...

Note that the following didn't work:

# didn't work; the controller didn't see the signed cookie
@request.cookie_jar.signed[:some_key] = "some value"
get :show ...
like image 72
balexand Avatar answered Oct 23 '22 06:10

balexand


In rails 3's ActionControlller::TestCase, you can set signed permanent cookies in the request object like so -

 @request.cookies.permanent.signed[:foo] = "bar"

And the returned signed cookies from an action taken in a controller can be tested by doing this

 test "do something" do
     get :index # or whatever
     jar = @request.cookie_jar
     jar.signed[:foo] = "bar"
     assert_equal jar[:foo], @response.cookies['foo'] #should both be some enc of 'bar'
 end 

Note that we need to set signed cookie jar.signed[:foo], but read unsigned cookie jar[:foo]. Only then we get the encrypted value of cookie, needed for comparison in assert_equal.

like image 8
Anthony Bishopric Avatar answered Oct 23 '22 04:10

Anthony Bishopric


After looking at the Rails code that handles this I created a test helper for this:

  def cookies_signed(name, opts={})
    verifier = ActiveSupport::MessageVerifier.new(request.env["action_dispatch.secret_token".freeze])
    if opts[:value]
      @request.cookies[name] = verifier.generate(opts[:value])
    else
      verifier.verify(cookies[name])
    end
  end

Add this to test_help.rb, then you can set a signed cookie with:

cookies_signed(:foo, :value => 'bar')

And read it with:

cookies_signed(:foo)

A bit hackish maybe, but it does the job for me.

like image 7
Roger Ertesvag Avatar answered Oct 23 '22 05:10

Roger Ertesvag