Как проверить cookies.permanent.signed в Rails 3
У меня есть действие в каком-то контроллере, который устанавливает какое-то значение в постоянном подписанном cookie, как это:
def some_action
cookies.permanent.signed[:cookie_name] = "somevalue"
end
И в каком-то функциональном тесте я пытаюсь проверить, правильно ли настроен файл cookie:
test "test cookies" do
assert_equal "somevalue", cookies.permanent.signed[:cookie_name]
end
Однако, когда я запускаю тест, я получил следующую ошибку:
NoMethodError: undefined method `permanent' for #
Если я попробую только:
test "test cookies" do
assert_equal "somevalue", cookies.signed[:cookie_name]
end
Я получил:
NoMethodError: undefined method `signed' for #
Как проверить подписанные куки в Rails 3?
5 ответов
Я натолкнулся на этот вопрос во время поиска в Google для решения аналогичной проблемы, поэтому я опубликую здесь. Я надеялся установить подписанный cookie в Rspec перед тестированием действия контроллера. Следующее сработало:
jar = ActionDispatch::Cookies::CookieJar.build(@request)
jar.signed[:some_key] = "some value"
@request.cookies['some_key'] = jar[:some_key]
get :show ...
Обратите внимание, что следующее не сработало:
# didn't work; the controller didn't see the signed cookie
@request.cookie_jar.signed[:some_key] = "some value"
get :show ...
В ActionControlller::TestCase rails 3 вы можете установить подписанные постоянные файлы cookie в объекте запроса следующим образом:
@request.cookies.permanent.signed[:foo] = "bar"
И возвращенные подписанные куки-файлы от действия, предпринятого в контроллере, можно проверить, выполнив
test "do something" do
get :index # or whatever
jar = @request.cookie_jar
jar.signed[:foo] = "bar"
assert_equal jar[:foo], @response.cookies['foo'] #should both be some enc of 'bar'
end
Обратите внимание, что нам нужно установить подписанный cookie jar.signed[:foo]
, но читать неподписанные куки jar[:foo]
, Только тогда мы получаем зашифрованное значение cookie, необходимое для сравнения в assert_equal
,
Посмотрев код Rails, который обрабатывает это, я создал тестовый помощник для этого:
def cookies_signed(name, opts={})
verifier = ActiveSupport::MessageVerifier.new(request.env["action_dispatch.secret_token".freeze])
if opts[:value]
@request.cookies[name] = verifier.generate(opts[:value])
else
verifier.verify(cookies[name])
end
end
Добавьте это в test_help.rb, затем вы можете установить подписанный файл cookie с помощью:
cookies_signed(:foo, :value => 'bar')
И читать это с:
cookies_signed(:foo)
Может быть, немного хакерский, но это делает работу для меня.
Проблема (по крайней мере, на первый взгляд) заключается в том, что в контексте функционального теста (ActionController::TestCase) объект "cookies" представляет собой Hash, тогда как при работе с контроллерами это ActionDispatch::Cookies::CookieJar объект. Поэтому нам нужно преобразовать его в объект CookieJar, чтобы мы могли использовать для него "подписанный" метод, чтобы преобразовать его в SignedCookieJar.
Вы можете поместить следующее в свои функциональные тесты (после запроса get) для преобразования файлов cookie из объекта Hash в объект CookieJar.
@request.cookies.merge!(cookies)
cookies = ActionDispatch::Cookies::CookieJar.build(@request)
Проблема также заключается в ваших тестах.
Вот некоторый код и тесты, которые я использовал для TDD ситуации, когда вы хотите установить значение cookie из передачи значения params в представление.
Функциональный тест:
test "reference get set in cookie when visiting the site" do
get :index, {:reference => "121212"}
refute_nil cookies["reference"]
end
SomeController:
before_filter :get_reference_code
ApplicationController:
def get_reference_code
cookies.signed[:reference] ||= params[:reference]
end
Обратите внимание, что строка refute_nil, cookie - это строка... это то, что также сделало этот тест не пройденным, поместив символ в cookies[:reference]
тест не понравился, поэтому я этого не делал.