水豚在查找和填写第一个表单元素时遇到问题

Capybara having trouble finding and filling in first form element

Capybara 似乎无法通过该表单元素标签内的显示文本 找到页面上的第一个表单元素。

Capybara 可以通过该标签的 for 值找到第一个表单元素,这看起来很奇怪。我在想 DOM 还没有加载,水豚可以连续搜索 for 值而不是 labels 中显示的文本?

这是我的相关表单元素的样子:

所以我应该能够通过显示的标签文本获取这些元素中的每一个:

fill_in "First Name", with: "foo"
fill_in "Last Name", with: "bar"
fill_in "Title", with: "some title"

这是我的规格:

scenario "with minimum fields while passing validations", js: true do
  visit "/"
  click_link "New Contact"
  fill_in "First Name", with: "foo"
  fill_in "Last Name", with: "bar"
  fill_in "Title", with: "some title"

  click_button "Create Contact"
  expect(page).to have_content "Success."
  expect(page).to have_content "foo bar"
end

它没有找到 First Name 表单元素,所以它没有填写它。它找到了 Last Name 元素和 Title 元素,因为我假设 DOM 有届时已满载:

这是html:

然而,奇怪的是:当我更改填写名字时:

fill_in "First Name, with: "foo"

收件人:

fill_in "contact_first_name, with: "foo"

它现在有效,但我不想使用 contact_first_namefor 值来获取该表单元素。我想使用显示的标签文本,因为我可以使用 TitleLast Name.

我错过了什么?为什么我不能使用 "First Name" 来获取 First Name 表单元素?

Update:事实证明,如果我将 sleep 1 放在 `fill_in "First Name" 之前,其中: "foo"然后就可以了!根据@TomWalpole 下面的评论,似乎有一个 javascript 库在阻碍?以下是我包含的所有 javascripts:

//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require twitter/typeahead.min
//= require nested_form_fields

如果页面加载缓慢,尤其是涉及到某些 Javascript 和/或 CSS 动画,请尝试将 Capybara.default_max_wait_time 提高到例如30 秒(默认为 2 秒)。 fill_in 应该开始工作了。

fill_in 以及大多数其他 Capybara 方法是 "synchronized",即它会重试搜索字段直到默认的最大等待时间,并且仅当在此之后未找到时时间,它失败了。

参见Capybara readme

Capybara 实际上是在查找输入并填充它,但随后该值被删除了。这是因为您有一些 JS 库在 Capybara 填充元素后将 functionality/behavior 添加到输入中。一旦 JS 增加了输入,它就会将其值重置为输入值 属性(与已更改的值属性相反),最终将其设置回空白。在第一个 fill_in 之前休眠是一种解决方法,除此之外这意味着弄清楚元素上的 JS 是什么 运行 并在调用 [=13 之前等待可检测到的变化(如果有的话) =].