Rails / Capybara-测试表单不提交

时间:2013-09-04 19:18:39

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

在我的Rails应用程序中,我使用以下jQuery通过在输入字段中按“enter”来禁用提交表单的功能:

$('input').on('keydown', function(e) {
  if(e.which == '13') {
    return false;
  }
})

我想用Capybara测试这个,但无法弄清楚如何。例如:

# the form being tested creates a new Shift object: 
test "enter does not submit form" do
  shift_count = Shift.count
  # fill in form, etc...
  page.driver.browser.execute_script "var e = jQuery.Event('keydown'); e.which = 13; $('#shift_employee').trigger( e );"
  assert Shift.count == shift_count
end

即使jQuery函数被注释掉,这个测试也会通过,大概是因为它在ActiveRecord有时间将新记录保存到数据库之前计算Shift.count

我还尝试让jQuery函数执行自定义$.get()请求,控制器以简单文本响应,认为这将构建足够的时间来完成所有服务器端工作。但这仍然不起作用,我认为这是因为,无论我如何设置jQuery函数,在我构建的任何AJAX内容之后,总是会提交表单并保存新记录。

关于如何可靠地测试表单未提交的任何想法?

2 个答案:

答案 0 :(得分:0)

所以表单提交是通过AJAX完成的吗?这是测试人员与Capybara一起运行的常见问题。你需要做的就是等待AJAX​​完成。

有两种方法可以做到这一点。一个是非常具体的,是首选的方法,另一个是通用的,只有在第一个方法无法完成的情况下才能使用。

第一种方法是等待DOM上的内容更改。在你的情况下,没有什么可能改变,但是,例如,如果你有一个警告,说“你不能按Enter键,你必须单击保存按钮!”然后你可以通过做类似的事情来等待:

page.driver.browser ... # your code
page.should have_css(".info", :text => "You cannot ...etc...")

当然,您不必使用:text选项。

另一种方法是创建一个辅助方法,如wait_for_ajax,在AJAX完成之前进行一般等待。

def wait_for_ajax
  start = Time.now
  while true
    break if (page.evaluate_script('$.active') == 0)
    if Time.now > start + Capybara.default_wait_time.seconds
      fail "AJAX did not register as complete after #{Capybara.default_wait_time} seconds!"
    end
    sleep 0.1
  end
end

这是基于人们用来检查AJAX的旧方式,但这个新脚本是Capybara 2.0的首选。

然后你的步骤会:

page.driver.etc
wait_for_ajax

wait_for_ajax方法可以进入Cucumber将加载的任何文件。

答案 1 :(得分:0)

我让Capybara重新访问该页面,然后检查Shift.count。当jQuery函数被注释掉时,测试现在失败,并且当函数被取消注释时传递。不过,我还是想知道是否有更好的方法。