rspec-rails: cookies.delete["cookie"] functionality seems to be broken with Rails 5.0.0beta3 and RSpec 3.4

I have code that does cookies.delete. If I debug it in my actual controller code, they are gone (and it works in the app itself). However, in the spec, the cookies are still there. I’m pretty sure this worked before I upgraded to Rails 5 (and pointed rspec to the master branch). I’ve tried everything I can think of, but I’m stumped.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 16 (6 by maintainers)

Most upvoted comments

I’ve just run into this on Rails 5.0.6. During its rewrite, it seems as though ActionController::TestCase forgot how to delete a cookie from the #cookies object (which is a CookieJar instance), unless the request method is set to GET.

In the context of a controller test, there are two instances of CookieJar involved; #request.cookie_jar and #cookies.

After the controller action under test has run, it calls #write on the request’s CookieJar, and then #update on the jar in #cookies.

https://github.com/rails/rails/blob/v5.0.6/actionpack/lib/action_controller/test_case.rb#L554

The call to #update only merges new cookies into the jar; it doesn’t delete any that ought to be removed.

However, the call to #write updates the “Set-Cookie” HTTP header, which does give us a workaround. When a cookie is being deleted the HTTP response will send a Set-Cookie header with the string "name_of_cookie=; ".

So you could assert that response.headers['Set-Cookie'] =~ /name_of_deleted_cookie=\; / is not nil.

It looks to me like fixing this in the #cookies jar will need some additional logic in the block I linked to above, deleting cookies from the #cookies jar.

This commit (https://github.com/rails/rails/pull/27586/files) did exactly that, but was reverted as it caused other regressions.

I’ve been calling cookies.update(response.cookies) after any non-GET requests where I need to test the contents of #cookies, which then allows me to test the contents of #cookies successfully.

Encountered this today and @gma comment helped me with this. The cookies.update(response.cookies) did the work.

Thanks a lot.

I faced this issue today with Rails 5.2(with Spree 3.7).

Before checking cookies content in spec after request, I did cookies.update(response.cookies) and it worked. Thanks @gma and @ganbootyard

This is a Rails issue, the code for updating cookies resides in https://github.com/rails/rails/blob/v6.0.0/actionpack/lib/action_controller/test_case.rb I suggest you construct a similar proof of concept in minitest and open it with them

@samphippen, I faced the same problem on Rails 5.0.0.1 and rspec (3.5.2 and 3.6.0.beta1). I’m just implementing a sign out feature, and it fails. Here is my controller code and controller spec.

RSpec.describe SessionsController, type: :controller do
  describe "POST #destroy" do
    it "delete :remember_token in cookies" do
      cookies.signed[:remember_token] = { value: 'remember_token', expires: 2.weeks.from_now }

      post :destroy

      expect(cookies.signed[:remember_token]).to be_nil
      expect(response).to redirect_to(root_path)
    end
  end
end
class SessionsController < ApplicationController
  def destroy
    cookies.delete(:remember_token)
    redirect_to root_path
  end
end

Failures:

  1. SessionsController POST #destroy delete :remember_token in cookies Failure/Error: expect(cookies.signed[:remember_token]).to be_nil
  expected: nil
       got: "remember_token"
# ./spec/controllers/sessions_controller_spec.rb:10:in `block (3 levels) in <top (required)>'

Finished in 0.05609 seconds (files took 5.34 seconds to load) 1 example, 1 failure

Failed examples:

rspec ./spec/controllers/sessions_controller_spec.rb:5 # SessionsController POST #destroy delete :remember_token in cookies

Here is the repo, https://github.com/chamnap/rails_5_cookie_problem. Let’s me know if I do anything wrong.