ChatGPT解决这个技术问题 Extra ChatGPT

在一些 JS 运行后如何让 Capybara 检查可见性?

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

我的集成测试如下所示:

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

当我在此测试运行的上下文中手动转到页面时,#blah 并不像我预期的那样可见。我怀疑 Capybara 正在查看页面的初始状态(在这种情况下不可见),评估 DOM 的状态并在 JS 运行之前未通过测试。

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

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

什么是驱动程序? XHR 完成后预期的 HTML 是什么?

u
underScorePassionFruit

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

在这里,您希望 Capybara 等待可见元素出现,这应该可以通过指定 visible 选项来实现:

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

我还没有尝试过,但如果您希望 find 始终等待可见元素,ignore_hidden_elements 配置选项在这里也可能很有用。


如果有人最初错过了@Kevin 的注释(比如我),您必须在包含块上有 js:true 才能使其正常工作。
这太棒了。它帮助我到达:expect(page).to have_selector('#flash-message', visible: false, text: "Signed in Successfully") - 感谢您发布此答案
在测试 jquery 向下滑动元素的可见性时,可见选项对我没有影响。我不得不使用 expect(find('#blah').visible?).to be_falsey。
我想要 is_visible 之类的东西?然后做其他事情
B
Björn Grossmann

这是另一种对我来说非常有效的方法:

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

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

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

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


should_not be_visible 在我看来不太好,因为 Capybara 在 Element#visible 时运行 wait_until { base.visible? }?被调用。
@phng-nguyn,#wait_until 已从 Capybara 的最新版本中删除。
这实际上是比“page.should have_selector ...”更好的变体,因为如果文本失败,则表示该元素实际上是显式不可见的,而提到的变体只是引发“没有匹配”错误,这有点令人沮丧。
这与公认的解决方案不同。对于这段代码,Capybara 只会等到元素在 DOM 中,然后立即检查可见性。如果您期望可见性发生变化,这可以为规范添加竞争条件。
有人知道 .should_not be_visible 是否涵盖 jQuery 设置的 display: none 吗?它似乎对我不起作用。
Z
Zubin

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

由于 ajax,您不能将 should_not 与 capybara 一起使用
@Marc-AndréLafortune,要使用 Capybara 测试 ajax,请使用 Capybara.javascript_driver。
使用 javascript_drive,have_css 将在放弃之前等待您的整个超时持续时间,因为它希望找到该元素。例如,您必须使用 should have_no_content 而不是 should_not have_content
expect(page).not_to have_selector("#some_element", visible: true) 使用 javascript_driver 对我来说效果很好,无需等待整个超时持续时间。
实际上,自从我发表评论以来,这已被更改,您现在可以(并且应该)使用 should_not,抱歉!
C
Ciro Santilli Путлер Капут 六四事

可见的意思并不明显

失败可能来自对什么被认为是可见或不可见的误解,因为它是不明显的,不是驱动程序可移植的,并且记录不足。一些测试:

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>

Rack 测试唯一认为不可见的是内联 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 和 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 的默认值:

它曾经是错误的(同时看到可见和不可见的元素),

目前是真的

由 Capybara.ignore_hidden_elements 选项控制。

Reference

完整的可运行测试 on my GitHub


很好的答案 - 感谢您为此付出的努力。使用多个驱动程序测试套件中元素的可见性并非易事。
“它曾经是假的(看到可见和不可见的元素),目前是真的,并由 Capybara.ignore_hidden_elements 选项控制。”有关详细信息,请参阅此博文:elabs.se/blog/60-introducing-capybara-2-1
M
Michael Gaskill

使用:

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

我正在测试使用 Cucumber 向用户发送通知并向用户显示通知状态消息的场景(具有内置 Capybara 支持的 cucumber-rails gem)

我试图测试具有 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 assert attributes of an element,它显示了如何以原始方式检查元素的属性。

我还在 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 assert attributes of an element 中建议的解决方案时的方法

我想出了以下内容:

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

s
smallsense

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

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

此解决方案与 wait_until 不兼容,因为 removed from Capybara 2
使用Timeout.timeout
更好地使用Selenium::WebDriver::Wait
如果你只使用硒
R
Robin Daugherty

接受的答案现在有点过时了,因为“应该”是不推荐使用的语法。这些天你最好按照expect(page).not_to have_css('#blah', visible: :hidden)的方式做一些事情


D
Dono

这里的其他答案是“等待”元素的最佳方式。但是我发现这不适用于我正在开发的网站。基本上,需要点击的元素在其背后的功能完全加载之前是可见的。这是几分之一秒,但我发现我的测试有时运行得如此之快,以至于它点击了按钮,但什么也没发生。我设法通过做这个临时的布尔表达式来解决它:

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 方法,但如果它不起作用,试试这个