水豚在 rspec 测试中不匹配单选按钮

Capybara not matching radio buttons in rspec test

我正在尝试使用 rspec 为 Bootstrap 表单编写测试。我有以下代码:

<div id="published" class="col-sm-auto">
  <div class="custom-control custom-radio custom-control-inline">
    <%= form.radio_button :published, true, checked: page.published?, class: 'custom-control-input' %>
    <%= form.label :published, 'Published', value: true, class: 'custom-control-label' %>
  </div>
  <div class="custom-control custom-radio custom-control-inline">
    <%= form.radio_button :published, false, checked: !page.published?, class: 'custom-control-input' %>
    <%= form.label :published, 'Hidden', value: false, class: 'custom-control-label' %>
  </div>
</div>

生成以下 HTML:

<div id="published" class="col-sm-auto">
  <div class="custom-control custom-radio custom-control-inline">
    <input class="custom-control-input" type="radio" value="true" name="page[published]" id="page_published_true" />
    <label class="custom-control-label" for="page_published_true">Published</label>
  </div>
  <div class="custom-control custom-radio custom-control-inline">
    <input class="custom-control-input" type="radio" value="false" checked="checked" name="page[published]" id="page_published_false" />
    <label class="custom-control-label" for="page_published_false">Hidden</label>
  </div>
</div>

当我 运行 这个测试时,它失败并显示消息

it 'should default to unpublished' do
  expect(page).to have_checked_field('Hidden')
end

发消息expected to find visible field "page[published]" that is checked and not disabled but there were no matches. Also found "", "", which matched the selector but not all filters.

查看检查器中的HTML,该字段可见且未禁用,并且有与文本匹配的标签。我不知道这两个空字符串是什么意思。

有人能告诉我为什么 have_checked_field 不匹配吗?我真的不热衷于编写一个更脆弱的测试,使用 has_csshas_xpath 来查找具有特定 ID 的输入标签——重点是用户应该看到一个标记为 [= 的字段30=] 并且应该检查它,不管幕后发生了什么!

我可以 99.9% 向您保证收音机输入实际上是不可见的,并且已被使用 CSS(可能还有一些 JS)的图像所取代。你可以做

expect(page).to have_checked_field('Hidden', visible: false)

或者你可以做一些稍微复杂的事情来验证标签是否确实可见,比如

expect(page).to have_css('input:checked + label', exact_text: 'Hidden')

如果您要处理大量此类单选按钮,另一种解决方案是编写自定义选择器类型,例如

Capybara.add_selector(:bootstrap_radio) do 
  xpath do |locator|
    XPath.descendant(:input)[XPath.attr(:type) == 'radio'].following_sibling(:label)[XPath.string.n.is(locator)]
  end

  filter(:checked) do |node, value|
    node.sibling('input[type="radio"]', visible: :hidden).checked? == value
  end
end

这将允许你做

expect(page).to have_selector(:bootstrap_radio, 'Hidden', checked: true)

然后如果需要,您可以编写像 have_checked_bootstrap_radio 这样的辅助方法。注意:这段代码是即兴的,所以 XPath/CSS 表达式可能不是 100% 正确,但总体思路是正确的:)