Setting cookie.signed in Rails 5 controller integration tests

Imagine a script that contains a controller integration test calls a controller method that is cookie.signed

used to do some kind of integrity check.

controller

# app/controllers/foo_controller.rb

def index
  entity = FooEntity.find_by_id(params[:id])
  if entity.nil?
    raise ActionController::BadRequest, 'Could not find requested entity.'
  else
    @is_authorized = entity.token == cookies.signed[:token]
    if @is_authorized
      # Success! The path to be tested.
    else
      raise ActionController::BadRequest, 'Unauthorized cookie token.'
    end
  end
end

      

Controller test

# app/test/controllers/foo_test.rb

require 'test_helper'

class FooControllerTest < ActionDispatch::IntegrationTest
  test 'should be working' do
    cookies.signed[:token] = '7e5201169ef160e31058d2a1976a5552'
    get '/foobar/123'
  end
end

      

However, I'm not sure how to get the installation cookie.signed

in the test. The above test code throws an exception:

NoMethodError: undefined method `signed for Rack :: Test :: CookieJar: 0x007fe90965ccd8

Tried to find a solution but the closest one I could find this article, https://sikac.hu/reconstruct-a-cookie-jar-and-read-signed-cookie-in-capybara-f71df387f9ff but couldn't figure out how to build the object ActionDispatch::Request

.

+3


source to share


1 answer


This appears to be a known bug in Rails 5 and up (a related issue - but the same applies to ). The problem is, in controller tests, the cookie heap is an instance of a class that doesn't support signed / encrypted cookies . On the other hand, in the application itself, a cookie jar is an instance of a class that supports both of these special types of cookies. cookies.encrypted

cookies.signed

Rack::Test::CookieJar

ActionDispatch::Cookies::CookieJar

However, to simply create a signed cookie in your controller test, you can manually create a chunk of the request cookie ActionDispatch

and use
to get the value of the signed cookie:

# app/test/controllers/foo_test.rb

require 'test_helper'

class FooControllerTest < ActionDispatch::IntegrationTest
  test 'should be working' do
    my_cookies = ActionDispatch::Request.new(Rails.application.env_config.deep_dup).cookie_jar
    my_cookies.signed[:token] = '7e5201169ef160e31058d2a1976a5552'

    cookies[:token] = my_cookies[:token]
    get '/foobar/123'
  end
end

      



The first test line creates a new request ActionDispatch

with the default application environment settings (these define, for example, the secret used to sign cookies) and returns its cookie jar. Then you just set the :token

signed cookie to the value you want (this cookie jar has a method signed

defined as ActionDispatch::Cookies::CookieJar

, not Rack::Test::CookieJar

). Finally, you will load the signed cookie value by accessing it without an accessory signed

and set the same test cookie name using that value.

Now when the test reaches the controller code, the controller should see the correct value in the cookie cookies.signed[:token]

.

+5


source







All Articles