我正在使用TestUnit,我想测试记住我的功能(当用户登录时)。
cookies变量(以及还需要/ response .cookies)仅包含没有过期时间的cookie值。
Rails以某种方式告诉网络浏览器什么时候cookie应该过期,所以我认为必须有办法检查cookie过期时间。
test "set permanent cookie" do
post :create, email: 'email', password: 'password', remember_me: true
# cookies[:auth_token] = random_string
# @request.cookies[:auth_token] = also_random_string
# @response.cookies[:auth_token] = also_random_string
end
问题是我只能得到cookie的值,而不能得到包含过期时间的哈希值。
答案 0 :(得分:4)
正如您所注意到的,cookies
Hash只包含post
调用后检查它的值(而不是到期时间)(这至少是Rails 2.3以来的行为)
您有两种选择:
首先,您可以检查response.headers["Set-Cookie"]
项目。它将包括那里的到期时间。但是,Set-Cookie
值只是一个字符串,您需要解析它。例如,cookies["foo"] = {:value => "bar", :expires => Time.now + 10.years }
会给你:
response.headers["Set-Cookie"]
# => "foo=bar; path=/; expires=Mon, 16-Aug-2021 21:54:30 GMT"
另一个选项(取自This Question/Answer)将存储cookie jar并确保它发送expires
值:
stub_cookie_jar = HashWithIndifferentAccess.new
controller.stub(:cookies) { stub_cookie_jar }
post :create, email: 'email', password: 'password', remember_me: true
expiring_cookie = stub_cookie_jar['expiring_cookie']
expiring_cookie[:expires].to_i.should be_within(1).of(1.hour.from_now.to_i)
答案 1 :(得分:2)
不幸的是,我无法在@ DylanMarkow的答案中找到或链接的解决方案,所以这里是我在检查“记住我”复选框时测试“永久”cookie的设置(测试受到影响/公然)从Test::Unit tests that DHH made in the commit that added cookies.permanent
to Rails复制。
测试使用RSpec和FactoryGirl。
<强>规格/请求/ authentication_requests_spec.rb 强>
require 'spec_helper'
describe "Authentication Requests" do
# ...
describe "authorization" do
# ...
describe "cookies" do
let(:user) { FactoryGirl.create(:user) }
subject { response.headers["Set-Cookie"] }
context "when remember me is set" do
before { sign_in_request(user) }
it { should =~ %r(.+expires.+#{20.years.from_now.year}) }
end
context "when remember me is not set" do
before { sign_in_request(user, remember_me: false) }
it { should_not =~ %r(expires) }
end
end
end
end
<强>规格/ utilities.rb 强>
def sign_in_request(user, remember_me: "true")
post session_path(
session: {
email: user.email,
password: user.password,
remember_me: remember_me
}
)
end
以下应用代码段使用i18n,Haml,Bootstrap和Simple Form语法:
应用/视图/会话/ new.html.haml 强>
= simple_form_for :session, url: session_path, html: {class: 'form-vertical' } do |f|
= f.input :email
= f.input :password
.checkbox
= f.input :remember_me, as: :boolean, label: false do
= check_box_tag :remember_me, 1, true
= label_tag :remember_me
= f.submit t('.signin'), class: "btn btn-large btn-primary"
应用/控制器/ sessions_controller.rb 强>
class SessionsController < ApplicationController
# ...
def create
if user = User.authenticate(params[:session][:email],
params[:session][:password])
sign_in user
flash[:success] = t('flash.successful_signin')
redirect_to root_url
else
flash.now[:error] = t('flash.invalid_credentials')
render 'new'
end
end
# ...
end
应用/模型/ user.rb 强>
class User < ActiveRecord::Base
has_secure_password
# ...
before_create :generate_authentication_token
def self.authenticate(email, password)
find_by_email(email).try(:authenticate, password)
end
private
def generate_authentication_token
begin
self.authentication_token = SecureRandom.urlsafe_base64
end while User.exists?(authentication_token: self.authentication_token)
end
end
应用/控制器/ application_controller.rb 强>
class ApplicationController < ActionController::Base
# ...
private
# A cookie that does not have an expiry will automatically be expired by
# the browser when browser's session is finished.
# cookies.permanent sets the expiry to 20 years
# Booleans seem to get passed from forms as strings
def sign_in(user)
if remember_me
cookies.permanent[:authentication_token] = user.authentication_token
else
cookies[:authentication_token] = user.authentication_token
end
self.current_user = user
end
helper_method :sign_in
def remember_me
params[:session].try(:[], :remember_me) == "true" ||
params[:remember_me] == "true"
end
# ...
end