一些JS运行后如何使水豚检查可见性?

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

我的集成testing看起来像这样:

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

当我手动去上下文中的这个testing运行,#blah是可见的,因为我期望。 我怀疑Capybara正在查看页面的初始状态(在这种情况下是不可见的),评估DOM的状态并在JS运行之前通过testing失败。

是的,我在包含describe块中设置:js => true 🙂

任何想法将不胜感激! 我希望我不必在这里有意拖延,这种感觉会很脆弱,会让事情变得缓慢。

我认为这里的find语句是隐含的等待状态,所以水豚会等待,直到页面上的元素,但不会等待它变得可见。

在这里,你会想要水豚等待可见的元素出现,这应该可以通过指定visible选项来实现:

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

我还没有尝试过,但是ignore_hidden_elementsconfiguration选项在这里也是有用的,如果你想find总是等待可见的元素。

这是另一种做法,对我来说完全合适:

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

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

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

这将断言一个元素已被隐藏。

如果你想检查一个元素是否在页面上,但是不可见, 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) 

使用:

  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(); 

我正在testing发送通知的情况,并使用Cucumber( 内置水豚支持的cucumber-rails gem)向用户显示通知状态消息。

我试图testing的id: notification_status元素是可见的我的步骤定义中的成功响应。为此我试着下面的语句:

page.find('#notification_status')。应该是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> 

这是预期的。

最后,我发现这个链接水豚断言一个元素的属性,显示了如何以原始的方式检查一个元素的属性。

我还发现在水豚文件可见? 方法( 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. 

因此,我得出的结论是,当testing一个元素的可见性不依赖于水豚可见的结果? 方法,当使用一个CSSselect器并且使用在链接水鸟元素的assert属性build议的解答

我想出了以下几点:

  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') 

什么可见的手段并不明显

失败可能来自于误认为可见或不可见,因为它是不明显的,而不是驱动程序可移植的,并且没有logging。 一些testing:

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> 

Racktesting认为是不可见的唯一的内联display: none (不是内部的CSS,因为它没有select器):

 !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和Js style.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上完全运行testing。

你可能想看看这个post ,它提供了一个等待所有ajax请求完成的示例方法:

 def wait_for_ajax(timeout = Capybara.default_wait_time) page.wait_until(timeout) do page.evaluate_script 'jQuery.active == 0' end end 

这里的其他答案是“等待”元素的最佳方式。 不过,我发现这并不适用于我正在工作的网站。 基本上,需要点击的元素在完全加载后面的函数之前是可见的。 这是在几分之一秒,但我发现我的testing运行速度很快,它点击button,什么都没有发生。 我设法通过做这个转换布尔expression式来解决它:

 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 

基本上它使用水豚默认的等待时间来寻找应该出现的东西,如果没有,它会重试你的点击。

再次,我会说,应该先尝试should have_selector方法,但如果它只是不会工作尝试这一点

现在接受的答案有点过时,因为“应该”是不赞成使用的语法。 这些日子,你会更好地沿着expect(page).not_to have_css('#blah', visible: :hidden)