Capybara和Rspec:在()和has_selector()中使用的正确方法是什么?

时间:2012-03-27 21:41:36

标签: ruby-on-rails ruby rspec capybara

我使用rspec 2.6.0和Capybara 1.1.1进行验收测试 有如下视图:

<tr >
  <td>Team 3 Name</td>
  <td>true</td>
  <td><a href="/teams/3">Show</a></td>
  <td><a href="/teams/3/edit">Edit</a></td>
  <td><a href="/teams/3">Deactivate</a></td>
</tr>
<tr >
  <td>Team 4 Name</td>
  <td>true</td>
  <td><a href="/teams/4">Show</a></td>
  <td><a href="/teams/4/edit">Edit</a></td>
  <td><a href="/teams/4">Deactivate</a></td>
</tr>

我想写一个验收测试,其中说:“团队3没有'停用'链接。”我希望以下内容失败:

within('tr', :text => 'Team 3 Name') do |ref|
  page.should_not have_selector('a', :text => 'Deactivate')
end

但它过去了。为了进一步测试正在发生的事情,我写了荒谬的话:

lock = false
within('tr', :text => 'Team 3 Name') do |ref|
  page.should have_selector('a', :text => 'Deactivate')
  page.should_not have_selector('a', :text => 'Deactivate')
  lock = true
end
lock.should be_true

也通过了。

我假设has_selector()调用的范围不受within()块的限制,但我不确定为什么会这样。水豚文档使用这种模式,似乎没有提到任何陷阱。 在内部使用以限制我的选择范围的正确方法是什么? 谢谢。 / Salernost

4 个答案:

答案 0 :(得分:12)

我自己还在学习Capybara,但您尝试过have_link而不是have_selector吗?另外我认为你不需要|ref|。例如:

lock = false
within('tr', :text => 'Team 3 Name') do # omit |ref|
  page.should have_link('Deactivate')
  page.should_not have_link('Deactivate')
  lock = true
end
lock.should be_true

<小时/> 2012年10月13日更新

与Capybara进一步讨论后,我在这里看到了几个潜在的问题:

  • within可能会默默地忽略text字段。您会注意到这些示例仅显示没有其他参数的CSS或XPath查找程序。
  • 如果within确实使用text,则可能无效,因为您要求它查看<tr>,但文字位于<td>。< / LI>
  • 即使您在page区块内,within主题很可能仍然以整个网页为目标。 within示例主要是关于使用fill_inclick。例外是Beware the XPath // trap下的示例。

至于创建within块,您可以为表行提供唯一的ID并使用CSS搜索它们,或者您可以编写针对第一个匹配行的特定XPath。

后者的问题是您要使用within上的<tr>,但您用于定位的文字位于<td>子元素内。因此,例如,此XPath应该找到包含文本Team 3 Name的表格单元格,但是您只对第一个单元格而不是整行进行within

within(:xpath, "//tr/td[normalize-space(text())='Team 3 Name'") do

有很多方法可以使用XPath“备份”到父元素,但我不知道如何做到这一点,我读到这不是一个好习惯。我认为你最好的选择就是生成id,这样你的行就会这样开始:

<tr id="team_3">

然后用简单的

来定位它们
within("tr#team_3")

答案 1 :(得分:5)

我还建议Mark Berry他提到的为每个表元素添加id的最终方法。

<tr id="team_3">

然后以

为目标
within("tr#team_3")

Capybara在选择xpath时给了我一些问题,因为它似乎并不一致,尤其是CI服务。

我还想在本节中注明相同的答案:

  

即使您在一个内部区域,页面主题仍然可以定位整个页面。内部示例主要是关于使用fill_in或click。例外情况是Beware the XPath // trap。

在旧版本中可能就是这种情况,但在当前版本的Capybara中,在page块内部调用within仅检查目标页面的部分。所以,使用Mark上面的例子:

within("tr#team_3") do
  expect(page).to have_content 'Team 3 Name'
  # => true
  expect(page).to have_content 'Team 4 Name'
  # => false
end

答案 2 :(得分:4)

have_selector似乎忽略了:text:content选项。我不得不使用这样的东西:

within 'a' do
  page.should have_content 'Deactivate'
end

答案 3 :(得分:3)

解决方案是不使用within方法:

expect(page).to have_css('tr#team_3') do
  without_tag('a', text: 'Deactivate')
end