在Capybara请求一个GET,它应该是一个POST

时间:2017-10-17 07:30:25

标签: ruby-on-rails ruby rspec capybara integration-testing

所以这是一个使用Docker的非常基本的Rails 5应用程序,它包括我从头开始构建的一些用户身份验证(不使用Devise等)。现在,我想开始学习与Capybara的请求规范,但我正在尝试使用它看起来很奇怪的问题。

这是我的登录表单(public class MyActivity extends Activity { //boolean field member initialized as false by default private boolean isLightOn; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.content_layout_id); final Button button = findViewById(R.id.button_id); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(isLightOn){ FlashTask.flash.off(); } else{ FlashTask.flash.on(); } isLightOn = !isLightOn; } }); } } ):

sessions.new.erb

我的<%= form_tag sessions_path do %> <form class="m-t" role="form" action="/"> <div class="form-group"> <%= text_field_tag :email, params[:email], class: 'form-control', placeholder: "Email Address", required: "" %> </div> <div class="form-group"> <%= password_field_tag(:password, nil, class: 'form-control', placeholder: "Password", required: "") %> </div> <div class="form-group"> <%= check_box_tag :remember_me, 1, params[:remember_me] %> <%= label_tag :remember_me %> </div> <div class="actions"><%= submit_tag "Log In", class: "btn btn-primary block full-width m-b" %></div> </form> <% end %>

requests/sessions_spec.rb

现在,如果你手动测试它会有效,所以我认为Capybara会看到同样的事情。但它一直都失败了。我已经配置了应用程序,因此如果您尝试访问受保护的控制器并且您尚未登录,则会将您重定向到require "rails_helper" RSpec.feature "Login", :type => :feature do scenario "handles wrong email and password gracefully" do visit login_path fill_in "Email Address", :with => "something" fill_in "Password", :with => "something" click_button "Log In" expect(page).to have_text("Email or password incorrect") end end 并闪烁显示/login的消息。 Rspec测试正在返回,这很奇怪 - 这表明Capybara试图访问另一页。

所以我把测试日志(Please log in to see this page

添加了

我发现的东西令我感到困惑:

docker-compose run web tail -f log/test.log

第一位没问题,GET Login由SessionsController #new处理。然后,(见第6行)由于某种原因,Capybara试图获取根URL,传递电子邮件/密码参数。我的根URL被映射到LocationsController#index,用户不允许访问,所以使用消息Started GET "/login" for 127.0.0.1 at 2017-10-17 06:59:26 +0000 Processing by SessionsController#new as HTML Rendering sessions/new.html.erb within layouts/empty Rendered sessions/new.html.erb within layouts/empty (1.1ms) Completed 200 OK in 6ms (Views: 6.1ms | ActiveRecord: 0.0ms) Started GET "/?email=something&password=[FILTERED]&commit=Log+In" for 127.0.0.1 at 2017-10-17 06:59:26 +0000 Started GET "/locations" for 127.0.0.1 at 2017-10-17 06:59:26 +0000 Processing by LocationsController#index as HTML Redirected to http://www.example.com/login Filter chain halted as :authenticate rendered or redirected Completed 302 Found in 2ms (ActiveRecord: 0.0ms) Started GET "/login" for 127.0.0.1 at 2017-10-17 06:59:26 +0000 Processing by SessionsController#new as HTML Rendering sessions/new.html.erb within layouts/empty Rendered sessions/new.html.erb within layouts/empty (1.1ms) Completed 200 OK in 6ms (Views: 4.9ms | ActiveRecord: 0.0ms) (0.4ms) ROLLBACK 重定向回/ login。该按钮实际上做的是发送一个POST到SessionsController #create。如果您在手动操作时查看日志,那确实会发生什么:

Please log in to see this page

我无法解决为什么在按下按钮时Capybara会为您手动点击按钮执行完全不同的请求。

非常感谢!

1 个答案:

答案 0 :(得分:1)

首先澄清一些。

  1. 您没有编写请求规范,而是编写功能规范(使用RSpec.feature:type => :feature
  2. 就是证明)
  3. 使用:type => :feature时,您无需指定RSpec.feature,因为已经设置了form_tag
  4. 现在谈谈你的问题。您在视图代码中嵌套了表单,因为<form>创建了一个<form>元素,然后您在其中直接有另一个rack-test元素(注意:发布实际的HTML总是更好,而不是erb所以人们可以看到实际的HTML是什么)。将其与您似乎使用js: true驱动程序(没有rack-test元数据)的事实相结合,当HTML无效时(嵌套表单是这样的),其行为与真实浏览器的行为不同,你最终得到了当前的行为。我猜想当你使用真正的浏览器时,内部表单元素被忽略,外部表单元素的方法属性等于“post”,因此它被发布。使用method时,它可能会提交没有<form class="m-t" role="form" action="/">属性的内部表单元素,因此默认为“get”。从视图中删除无关的tf vc scorch表单元素,应该可以正常工作。