在运行某些JS后,如何使Capybara检查可见性?


82

加载页面后,我将根据xhr返回的数据运行,隐藏和显示各种项目的代码。

我的集成测试如下所示:

it "should not show the blah" do
    page.find('#blah').visible?.should be_true
end 

当我手动去到页面的背景下,本次测试运行,#blah是不是如我所料可见。我怀疑Capybara正在查看页面的初始状态(在这种情况下是不可见的),评估DOM的状态并在JS运行之前未通过测试。

是的,我:js => true在包含的describe块上设置了:)

任何想法将不胜感激!我希望我不必在这里故意拖延,那会感觉片状并且会减慢速度。


1
司机是什么?XHR完成后,预期的HTML是什么?
Ciro Santilli郝海东冠状病六四事件法轮功

Answers:


132

我认为find这里的语句是带有隐式等待的语句,因此Capybara将等待直到元素在页面上,但不会等待它变为可见。

在这里,您希望水豚等待可见元素的出现,这可以通过指定以下visible选项来实现:

expect(page).to have_selector('#blah', visible: true)

我还没有尝试过,但是ignore_hidden_elements如果您想find一直等待可见元素,则配置选项在这里也可能很有用。


6
万一有人最初错过了@Kevin的笔记(像我一样),则必须js:true在包含块上才能起作用。
克里斯·贝克

3
这太棒了。它帮助我到达:expect(page).to have_selector('#flash-message', visible: false, text: "Signed in Successfully")-感谢您发布此答案
Chuck Bergeron

测试jQuery向下滑动元素的可见性时,visible选项对我没有任何影响。我必须使用Expect(find('#blah')。visible?)。成为be_falsey。
trueinViso

我想要类似is_visible的东西吗?然后执行其他操作
user1735921 2016年

37

这是另一种对我来说效果很好的方法:

find(:css, "#some_element").should be_visible

特别是对于更复杂的发现,例如

find(:css, "#comment_stream_list li[data-id='#{@id3}']").should_not be_visible

可以断言元素已被隐藏。


1
should_not be_visible不好看我作为水豚运行wait_until { base.visible? }时元#可见?被调用。
PHUONG阮

1
@ phng-nguyn,#wait_until已从水豚的最新版本中删除。
solidcell

3
实际上,这是比“ page.should have_selector ...”更好的变体,因为如果出现文本失败的情况,则表示该元素实际上是显式不可见的,而提到的变体只是引发“没有匹配项”错误,这有点令人沮丧。
installero

这与接受的解决方案不同。对于此代码,Capybara将只等到元素位于DOM中,然后立即检查可见性。如果您希望能见度发生变化,则可以在规格中添加竞争条件。
johncip '16

1
有人知道jQuery是否设置.should_not be_visible封面display: none吗?它似乎对我不起作用。
Antrikshy

20

如果要检查页面上是否有某个元素,但该元素不可见,visible: false将无法正常工作。让我难过了一点。

方法如下:

# assert element is present, regardless of visibility
page.should have_css('#some_element', :visible => false)
# assert visible element is not present
page.should have_no_css('#some_element', :visible => true)

1
您不能使用should_not与水豚,因为AJAX的
马克-安德烈·Lafortune

@Marc-AndréLafortune,要使用capybara测试ajax,请使用Capybara.javascript_driver。
Zubin

1
使用javascript_drive,have_css将等待整个超时时间,然后再放弃,因为它希望找到该元素。例如,您必须使用should have_no_content而不是should_not have_content
马克-安德烈·Lafortune

1
expect(page).not_to have_selector("#some_element", visible: true)使用javascript_driver,对我来说效果很好,而无需等待整个超时时间。
Jason Swett

1
实际上,自从我的评论以来,此内容已更改,您可以(并且应该)should_not现在使用,对不起!
马克-安德烈·Lafortune

9

使用:

 Ruby:     ruby 1.9.3dev (2011-09-23 revision 33323) [i686-linux]
 Rails:    3.2.9
 Capybara: 2.0.3

我有一个Rails应用程序,其中有一个链接,单击该链接应提交AJAX发布请求并返回JS响应。

链接代码:

 link_to("Send Notification", notification_path(user_id: user_id), remote: true, method: :post)

JS响应(.js.haml文件)应在链接存在的页面上切换以下隐藏的div:

 #notification_status(style='display:none')

js.haml文件内容:

:plain
  var notificationStatusContainer = $('#notification_status');
  notificationStatusContainer.val("#{@notification_status_msg}");
  notificationStatusContainer.show();

我正在测试使用黄瓜发送通知并向用户显示通知状态消息的场景(带有内置Capybara支持的黄瓜导轨宝石

我试图测试具有ID:notification_status的元素在步骤定义中成功响应时可见,为此,我尝试了以下语句:

page.find('#notification_status').should be_visible
page.should have_selector('#notification_status', visible: true)
page.should have_css('#notification_status', visible: true)
page.find('#notification_status', visible: true)
page.find(:css, 'div#notification_status', visible: true)

以上都不是我的工作,也没有使我成功。以上列出的5个片段中,最后4个片段失败,并出现以下错误:

'expected to find css "#notification_status" but there were no matches. Also found "", which matched the selector but not all filters. (Capybara::ExpectationNotMet)'

这很奇怪,因为以下语句正确传递了:

page.has_selector?('#notification_status')

实际上,我使用

  print page.html

出现了

<div style='' id='notification_status'></div>

这是预期的。

最终,我发现此链接的“水豚”断言了元素的属性,从而展示了如何以原始方式检查元素的属性。

我也可以在Capybara文档中找到可见的内容吗?方法(http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method)以下信息:

 Not all drivers support CSS, so the result may be inaccurate.

因此,我得出的结论是,在测试某个元素的可见性时,不依赖于Capybara可见性的结果吗?使用CSS选择器并使用链接Capybara中建议的解决方案时的方法断言元素的属性

我想出了以下几点:

 module CustomMatchers
   def should_be_visible(css_selector)
    find(css_selector)['style'].should_not include('display:none', 'display: none')
   end
 end

 World(CustomMatchers)

用法:

should_be_visible('#notification_status')

8

可见的含义不明显

该故障可能是由于对不可见的内容,对驱动程序的移植性不佳以及文档不足而造成的误解。一些测试:

HTML:

<div id="visible-empty"                                                                   ></div>
<div id="visible-empty-background"      style="width:10px; height:10px; background:black;"></div>
<div id="visible-empty-background-same" style="width:10px; height:10px; background:white;"></div>
<div id="visible-visibility-hidden"     style="visibility:hidden;"                        >a</div>
<div id="visible-display-none"          style="display:none;"                             >a</div>

机架测试认为唯一不可见的是内联的display: none(不是内部CSS,因为它不执行选择器):

!all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Poltergeist的行为类似,但是可以处理内部CSS和Jsstyle.display操纵:

Capybara.current_driver = :poltergeist
!all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Selenium的行为大不相同:如果认为一个空元素不可见,visibility-hidden并且display: none

Capybara.current_driver = :selenium
 all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
 all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

另一个常见的问题是默认值visible

  • 它使用的是false(看到两个可见和不可见的元素),
  • 目前是 true
  • Capybara.ignore_hidden_elements选项控制。

参考

在我的GitHub上进行全面的可运行测试。


1
很好的答案-感谢您为此付出的努力。使用多个驱动程序测试套件中元素的可见性并非易事。
安迪·特里格斯

1
“它曾经是错误的(看到可见和不可见的元素),目前是真实的,并且由Capybara.ignore_hidden_​​elements选项控制。” 有关更多信息,请参见此
rizidoro 2015年


2

现在已经接受的答案有点过时了,因为“ should”已经过时了。如今,您最好按照以下方式做一些事情:expect(page).not_to have_css('#blah', visible: :hidden)


1

这里的其他答案是“等待”该元素的最佳方法。但是我发现这不适用于我正在处理的网站。基本上,需要单击的元素在完全加载背后的功能之前就可见。这只是几分之一秒,但我发现我的测试有时运行得如此之快,以至于它单击了按钮并没有任何反应。我设法通过执行以下临时布尔表达式来解决此问题:

if page.has_selector?('<css-that-appears-after-click>')
  puts ('<Some-message-you-want-printed-in-the-output>')
else
  find('<css-for-the-button-to-click-again>', :match == :first).trigger('click')
end

基本上,它使用capybara默认的等待时间来查找应显示的内容,如果不存在,它将重试单击。

再一次,我会说should have_selector应该首先尝试该方法,但是如果它无法正常工作,请尝试此方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.