2

I'm trying to set a cookie in my integration tests, like so:

cookies.signed[:test] = 1

This fails with:

NoMethodError: undefined method 'signed' for #<Rack::Test::CookieJar>

As far as I can tell, this is because the only kind of cookiejar that supports 'signed' is the ActionDispatch::Cookies::CookieJar kind.

I've tried the workaround outlined here, but then I get:

NoMethodError: undefined method 'env' for nil:NilClass

Some diving into the rails source showed me that this is due to the fact that I'm passing in a nil 'request' object.

It turns out that request is nil no matter how I try to get it - @request is nil, self.request is nil, open_session.request is nil - there's no way to get a non-nil 'request' object.

If I attempt to create my own request object, I get the error mentioned by this person, but none of the solutions posted there work for me.

As you can probably guess, I've been bashing my head against the wall all morning trying to find out what I've missed. Is there a way to set this signed cookie?

Community
  • 1
  • 1
Atiaxi
  • 1,637
  • 1
  • 13
  • 18

3 Answers3

2

This seems to be fixed in Rails 3.2, I can use

cookies.signed[:test] = 1

without troubles now.

Anyway, if you ever need to set a signed cookie on a request manually (which is just a hash), you can use the following code to generate:

request.cookies['test'] = ActiveSupport::MessageVerifier.new(Rails.application.config.secret_token).generate(1)
Michael Reinsch
  • 579
  • 4
  • 8
  • 1
    No, you can't. In Rails 3.2.13 in request tests `cookies` still return a `Rack::Test::CookieJar`. – Janko Jun 11 '13 at 20:36
1

As far as Rails 5 goes, to generate a signed cookie within an integration test, I've found the following helper method to be very useful:

def generate_signed_cookie_value(value, digest = 'SHA1', serializer = Marshal)
  salt   = Rails.application.config.action_dispatch.signed_cookie_salt
  secret = Rails.application.key_generator.generate_key(salt)

  ActiveSupport::MessageVerifier.new(secret, digest: digest, serializer: serializer).generate(value)
end

Then in your integration test you could do the following:

test 'something using signed cookies' do
  self.cookies['my-signed-cookie'] = generate_signed_cookie_value('some-value')

  get '/'

  # cookies.signed['my-signed-cookie'] should be valid now
end
mikeycgto
  • 3,368
  • 3
  • 36
  • 47
1

Answering my own question because I found a workaround:

In my case, I was attempting to set that cookie because the controller I was testing depended on it being set. However, in the actual app, there's another controller that actually sets the cookie to begin with. This being an integration test, I'm now free to call that other controller and have it do what I was trying to do all along. It's a bit more cumbersome and slower, but it gets the job done.

Atiaxi
  • 1,637
  • 1
  • 13
  • 18