Atiaxi
Atiaxi

Reputation: 1647

Can't test signed cookies in rails 3 integration tests

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?

Upvotes: 2

Views: 1453

Answers (3)

mjc
mjc

Reputation: 3426

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

Upvotes: 1

Michael Reinsch
Michael Reinsch

Reputation: 579

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)

Upvotes: 2

Atiaxi
Atiaxi

Reputation: 1647

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.

Upvotes: 1

Related Questions