在michael hart'l的rails教程中,我无法理解规范:
require 'spec_helper'
describe "Authentication" do
.
.
.
describe "authorization" do
.
.
.
describe "as wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in user, no_capybara: true }
describe "visiting Users#edit page" do
before { visit edit_user_path(wrong_user) }
it { should_not have_title(full_title('Edit user')) }
end
describe "submitting a PATCH request to the Users#update action" do
before { patch user_path(wrong_user) }
specify { expect(response).to redirect_to(root_url) }
end
end
end
end
如您所见,作者在每个示例之前使用before { sign_in user, no_capybara: true }
登录用户。 no_capybara
选项声明为:
规格/支持/ utilities.rb
.
.
.
def sign_in(user, options={})
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
正如他在教程中指出的那样:当直接使用其中一种HTTP请求方法(get,post,patch或delete)时,这是必要的(他的意思是no_capybara选项),我可以理解为“向用户提交PATCH请求#news操作“正在使用补丁方法,但上面的sign_in方法与此行(补丁方法)之间的关系是什么,在我的理解我认为 sign_in 使用 使用补丁,所以为什么我们应该添加 no_capybara 这个选项>
答案 0 :(得分:2)
我对同一部分的测试失败了这些消息:
Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/signin>.
对你来说是一样的吗?网址为“http://www.example.com/”对您来说不奇怪吗?我们在应用程序的任何位置都没有使用此URL。那是Capybara这样做的。这意味着,正如所有其他人所说的那样,Capybara实际上并没有在我们的实际应用程序中创建cookie,它只是在模拟登录。我们将不得不在Capybara的文档中进行更多搜索,以便在这一点上准确理解它是如何工作的。但是你看到Capybara没有进行实际登录。现在,如果你看到我们的users_controller.rb
:
before_action :signed_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
反过来,做:
def signed_in_user
redirect_to signin_url, notice: "Please sign in." unless signed_in?
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
因此,当测试要求:
before { get edit_user_path(wrong_user) }
它会被控制器自动重定向到signin_url
,因为正如我之前所说,用户并没有真正登录,没有为他设置任何cookie。这就是为什么必须提前设置cookie。
答案 1 :(得分:0)
看起来他只是想制作一个更快/更少依赖的测试套件。当您使用Capybara驱动程序完成登录过程时,最终结果是您在浏览器中放置了一个cookie,这是请求之间用户会话的持续时间。
通过提供“no_capybara”选项,您可以避免呈现登录页面,查找并填写所有信息,提交页面,然后在登录后重定向到第一页。你想要的只是浏览器中的cookie,所以他只是直接设置它并跳过其他所有内容。
答案 2 :(得分:0)
no_capybara是必需的,因为水豚不能直接提交'补丁'或'放'HTTP方法。
请参阅:Why Capybara can't submit directly to put action?
由于水豚无法提交投放/补丁,我们需要手动进行更改,这就是为什么Micheal使用:no_capybara选项来识别这种情况。
答案 3 :(得分:0)
我遇到了同样的问题,我无法理解为什么在使用直接HTTP请求时应该使用其他类型的登录。
我再次阅读了Michael Hartl教程的一些部分,原因似乎是cookies对象在测试中的工作方式不同,因为它只是一个模拟。因此,对于直接的http请求,您不能只填写表单并使用“常规”sign_in。您必须使用:no_capybara选项将remember_token直接设置为cookie。
我希望作者的评论有所帮助:
如注释行中所述,填写表单在不使用Capybara时不起作用,因此为了涵盖这种情况,我们允许用户传递选项no_capyabara:true以覆盖默认的signin方法并直接操作cookie 。当直接使用其中一个HTTP请求方法(get,post,patch或delete)时,这是必要的,如代码清单9.45所示。 (请注意,测试cookie对象不是真正的cookie对象的完美模拟;特别是,代码清单8.19中所见的cookies.permanent方法在测试中不起作用。)正如您可能怀疑的那样,sign_in方法将证明是有用的在未来的测试中,事实上它已经可以用来消除一些重复(第9.6节)。
答案 4 :(得分:0)
这可能为时已晚,但这是我的理解。 如果您使用Capybara作为登录的驱动程序,他会在HIS cookie中保留remember_token。但是,下一个PATCH请求将由另一个人提交,因为Capybara无法直接将该请求发送到Web服务器。在这种情况下,发送请求的人在用于登录的cookie中没有remember_token。这就是测试出错的原因。
这不是启动问题。