0

在 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选项声明如下:

规范/支持/实用程序.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 选项),我可以理解这一点,在“向Users#update action”有一个 补丁方法在使用,但是上面的sign_in方法和这一行(补丁方法)之间有什么关系,据我了解,我认为在使用补丁之前使用了sign_in ,所以为什么我们应该添加这个选项no_capybara _

4

5 回答 5

2

我对同一部分的测试因以下消息而失败:

Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/signin>.

你也一样吗?URL 是“ http://www.example.com/ ” ,你不觉得奇怪吗?我们没有在应用程序的任何地方使用此 URL。那是水豚做的。这意味着,正如所有其他人所说,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。

于 2014-03-31T14:55:41.857 回答
0

no_capybara 是必需的,因为 capybara 不能直接提交到 'patch' 或 'put' HTTP 方法。

见:为什么 Capybara 不能直接提交 put action?

由于 capybara 无法提交到 put/patch,我们需要手动进行更改,这就是为什么 Micheal 使用 :no_capybara 选项来识别这种情况。

于 2013-09-05T04:41:29.620 回答
0

看起来他只是想制作一个更快/更少依赖的测试套件。当您使用 Capybara 驱动程序完成登录过程时,最终结果是您会在浏览器中放置一个 cookie,这就是在请求之间保持用户会话的原因。

通过提供“no_capybara”选项,您可以避免渲染登录页面、查找并填写所有信息、提交页面,然后在登录后重定向到第一页。浏览器中的 cookie 中包含您想要的所有内容,因此他只是直接设置并跳过其他所有内容。

于 2013-09-05T02:43:37.040 回答
0

这可能为时已晚,但这是我的理解。如果您使用 Capybara 作为驱动程序登录,他会持有 HIS cookie 中的 remember_token。然而,下一个 PATCH 请求将由其他人提交,因为 Capybara 没有能力直接将该请求发送到 Web 服务器。在这种情况下,发送请求的人在用于登录的 cookie 中没有 remember_token。这就是测试出错的原因。

这与发起问题不同。

于 2014-02-17T12:49:00.690 回答
0

我遇到了同样的问题,我也不明白为什么在使用直接 HTTP 请求时应该使用另一种登录方式。

我再次阅读了 Michael Hartl 教程的某些部分,原因似乎是 cookie 对象在测试中的工作方式并不完全相同,因为它只是一个模拟。因此,对于直接的 http 请求,您不能只填写表格并使用“常规”登录。您必须使用 :no_capybara 选项将 remember_token 直接设置到 cookie 中。

我希望作者的这个评论有帮助:

如注释行所述,不使用 Capybara 时无法填写表单,因此为了涵盖这种情况,我们允许用户传递选项 no_capyabara: true 以覆盖默认登录方法并直接操作 cookie。当直接使用其中一种 HTTP 请求方法(get、post、patch 或 delete)时,这是必需的,我们将在代码清单 9.45 中看到。(请注意,测试 cookie 对象并不是对真实 cookie 对象的完美模拟;特别是,清单 8.19 中的 cookies.permanent 方法在测试中不起作用。)您可能会怀疑,sign_in 方法将被证明是有用的在未来的测试中,事实上它已经可以用来消除一些重复(第 9.6 节)。

于 2013-10-07T06:41:23.843 回答