Reputation: 1647
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
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
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
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