Testing cookies in RailsEdit

Resources

My initial attempts at testing cookies while doing Behaviour-Driven Development with Rails were not successful so I started to look for resources to investigate the problem:

The cookies being read are what were received along with the request, the cookies being written are what will be sent out with the response.

Use a string for [the] cookie name, symbol [sic] somehow returns nil in functional test.

Summary

Adapting the available information for use with RSpec, we have:

Setting up a request cookie before a spec

before do
  request.cookies['foo'] = CGI::Cookie.new('name' => 'foo', 'value' => '12')

  # shorter alternative
  request.cookies['foo'] = CGI::Cookie.new('foo', '12')
end

Note that:

  • You must use request.cookies, not cookies
  • You must use a String key, not a Symbol
  • You must set a CGI::Cookie value, not just a String

If you get any of those things wrong then your controller won’t be able to get the cookies that you’ve set in your specs.

To confirm that you really did set the cookie you can check it; unlike the normal cookie, request.cookies does allow key look-ups:

request.cookies['foo'].should == '12'

Firing a controller method

You may then fire off a controller method:

# example: getting the "show" action
get 'show'

Directly calling a method using send, for example, will not work because the cookies will not be set up for the controller.

In the controller

Inside the controller itself you can read and write cookies as normal. Note the use of Symbol keys:

# reading
cookies[:foo]

# writing
cookies[:foo] = 'hello world'

# deleting (clears cookie from user's browser as well
cookies.delete :foo

Checking a response cookie is set in a spec

After firing off the controller you can confirm that it set or unset any cookies before sending the result back to the user:

cookies['user_id'].should be_blank

Note that:

  • This time we use cookies and not request.cookies
  • Again it is compulsory to use a String as a key, not a Symbol
  • Use the blank? method because it handles more cases than empty?