Requiring and Testing Cookies

Requirement: Users must have cookies enabled to use the site. If they don't: give them some sort of graceful warning to let them know there's going to be trouble. Doesn't sound too bad… it ended up being much more of an adventure than I had expected.

Step 1. Add the cookie requirement

After a bit of deliberation I decided that I would rather not use Javascript (if I didn't have to). The trouble with testing for cookies with _only_ server side code is… well, you are _only_ on the server side – and 'cookies enabled' isn't exactly a server setting 🙂 . When setting a cookie value – you are merely setting it in a hash to be persisted later (when the request finishes processing) – therefore you won't really know if it is going to _work_ in the browser until… well… you actually try to set it in the browser.

As you likely know, rails uses a cookie by default to track the session id (cookie id is :_session_id). So, it seems easy enough that I can verify that cookie is there to determine if cookies are enabled.

The catch, of course, is that on the first request: my code will check if the cookie is present… see that it isn't (the browser didn't _already_ have it) and conclude that cookies are disabled! That's not going to work: in all likelihood they are enabled… it's just a matter of me not getting a chance to set the thing yet.

So, I'm going to drop in a little workaround:

First check for the _session_id cookie. If it's there: great, we're good to go. Mission accomplished: proceed to the requested functionality with my blessings.
If not, what do we know? Not much. We know that the cookie hasn't _already_ been added, but we don't know if that's because it's actually been blocked… or have we just not even attempted it yet? What's the easiest way to determine if this is the first time the application has been accessed? Personally, I think it's to not even try to figure it out and just make another call: when that call is fielded you _know_ it's not the first!

So, we add a 'special' parameter and repeat the users request. The subsequent request will be able to check not only for the presence of our cookie but also for the presence of our special parameter – if both turn up negative: we can conclude that cookies are disabled.

before_12345.png
Step 2. Add the unit tests

Alright, so all my functional tests are suddenly failing since they are all being blocked by the cookie requirement! I need to add my simple test for the code I just added – while also modifying the existing tests to have proper credentials to access the app. No prob, right? I already have my tests jumping through a little hoop to properly 'login', so now in addition to the "authenticate" stuff I already have: I just add a piece of code to add my cookie:
first_cookie_test.png

Run the tests… trouble. The cookie isn't being found. This does make some sense: what does "cookies" really mean to my test class? So, I change things so that instead of saying cookies[:_session_id], I say:

final_cookie_test.png

Now this works for the test… but now it isn't working in the actual web app!

Step 3. Making it WorkI suppose I could drop in another piece of code to have my filter check both cookies and @request.cookies but that's no good. I need to use @request.cookies for both test and 'application' code.
The final snags…

a. @request.cookies won't play nice with my symbol ( :_session_id ), so I need to actually use a string for the key ("_session_id").

b. @request.cookies["_session_id"] is returning a Hash and is also returning blank instead of null if not found

So… without further adu:

The test code:

final_cookie_test.png

The app code:

after_12345.png

As with everyting Rails: the end solution is so simple it's painful.

And they lived happily ever after, The End.

Advertisements

6 Comments

Filed under Cookies, rails, Ruby, Test Driven Development (TDD)

6 responses to “Requiring and Testing Cookies

  1. Nice trick! Thank you, Jim.

    Any idea why @request.cookies won’t play nice with the “:_session_id” symbol? Would that be because of the way things get serialized into the actual request and the browser is having problems?

  2. kirstin

    Rails uses session cookies, which aren’t persistant, and can’t be disabled.

  3. That’s right Kirstin. This is not about making a rails app work w/o cookies… it’s about presenting the user with a graceful message when cookies are disabled + testing that it all works.

  4. Hey James, thanks for this post. I’ve created a plug-in based on your idea: http://svn.jonahb.com/projects/cookie_requirement

  5. Pingback: Duplo » Blog Archive » Rails Cookie Detection

  6. Jeff

    Thank you, Jim! This article has neatly solved the issues I’ve been struggling with for days now. Hooah!

    –Jeff

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s