I am unable to test the presence of a signed cookie in a controller. I would expect the test case below to pass and it was passing before I upgraded rails and rspec-rails gems. Is this an issue with rspec-rails or a mistake on my side?
class ApplicationController < ActionController::Base
helper_method :user_signed_in?
def user_signed_in?
cookies.signed[:user_session_key].present?
end
end
RSpec.describe ApplicationController do
describe "user_signed_in?" do
context "when logged in" do
it "returns true" do
cookies.signed[:user_session_key] = "1234"
expect(subject.user_signed_in?).to eq(true)
end
end
end
end
This functionality is all Rails as far as I'm aware, have you added the rails-controller-test
gem?
I have a similar problem, I can't set a cookies.encrypted
key like I could in Rails 4.2/RSpec 3.4. I was looking at the docs for help, but they seem a little outdated.
Edit: I'm using rails-controller-test
and only seems to be a problem when testing an Anonymous controller in ApplicationController.
Sample app: https://github.com/dsandstrom/rspec_cookies_5
Looks like we have the same issue @dsandstrom, it only seems to be the case when I'm using subject
as the controller. I'm also using rails-controller-test
gem.
Signed cookies work fine in the Rails application itself, just not when they are set in the controller spec for a test
Thanks for the issue. Your reproduction spec above is useful, but it'd be great if we had a repository we could clone to reproduce this.
Could you please provide us with a rails app that we can clone that demonstrates the issue. Specifically it'd be great if
1) you could rails new
an application and commit
2) make all the changes necessary to reproduce the issue and commit
then, provide us with a description of how to clone your application and reproduce the issue.
Thanks :)
@samphippen https://github.com/dsandstrom/rspec_cookies_5
Check out tests in application_controller_spec.rb. The first one pases, but the second one, that uses the ApplicationController method, doesn't.
Confirmed.
I spent some time trying to figure out where the bug is, but was not successful. I also tried to reproduce with minitest, but couldn't figure out how to set an encrypted cookie. I don't have a lot of experience with the built in test framework.
I have the same problem. With Rails 4.2.1 all Rspec tests regarding signed cookies passed. However, since I have upgraded to Rails 5.0.0 the value returned for all signed cookies keys is nil.
ae29142142324545a328948e059e8b8118fd7a33 is the commit in rails which introduces this
the cause is that "subject.cookies" (i.e. the cookies
on the controller) returns a different cookiejar object to the cookies in the spec because of this line: https://github.com/rails/rails/commit/ae29142142324545a328948e059e8b8118fd7a33#diff-873380f872919a451b4e8ce9dcbd57f7R22
I've been looking into this issue more and found a weird work around: call cookies from the AnonymousController:
def index
cookies
render text: "success"
end
The cookie gets encrypted and set correctly, but for some reason, it doesn't get passed along until it's manually access. I have no idea why this works, but hopefully it helps with debugging.
From the linked commit, it looks like we need to send the cookie along with the request, but I couldn't figure out how to do that with neither headers
nor env
params. There is also a Rails test that kinda does what we want: https://github.com/rails/rails/blob/v5.0.0.1/actionpack/test/dispatch/cookies_test.rb#L597 . However, that seems overly complicated and, again, I couldn't get it to work.
@sgrif hi
Hi,
a workaround could be this:
cookies.signed[:foo] = 'bar'
allow(controller).to receive(:cookies).and_return(cookies)
So we'll force the controller to use the cookiejar object of the test.
This issue is not a bug in rspec. It can be reproduced with Rails alone using a normal Rails controller test. I have opened https://github.com/rails/rails/issues/27145 with a reproduction script. This issue can be closed.
cc @samphippen
Maybe like this?
Put this in config/initializers/signed_cookies_patch_test.rb
:
if Rails.env.test?
class ActionDispatch::Cookies::CookieJar
def encrypted; self; end
def signed; self; end
end
end
@ivko999 's solution worked for me - thanks!
Even cleaner, just put it in a spec/support
file:
# spec/support/cookies.rb
class ActionDispatch::Cookies::CookieJar
def encrypted; self; end
def signed; self; end
def permanent; self; end # I needed this, too
end
This worked for me
before(:each) do
allow_any_instance_of(Rack::Test::CookieJar).to receive(:encrypted) { |object| object }
allow_any_instance_of(ActionDispatch::Cookies::CookieJar).to receive(:encrypted) { |object| object }
end
It didn't pollute other tests.
I needed both because setting seemed to use rack and reading used action dispatch. Odd but I got green only when both were present.
Most helpful comment
@ivko999 's solution worked for me - thanks!
Even cleaner, just put it in a
spec/support
file: