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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8801845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:40:03  来源:igfitidea点击:

How to make Capybara check for visibility after some JS has run?

rubyrspeccapybaraintegration-testing

提问by Kevin Davis

After loading a page I have code that runs and hides and shows various items based on data returned by an xhr.

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

My integration test looks something like this:

我的集成测试如下所示:

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

When I manually go to the page in the context this test runs, #blah is notvisible as I expect. I suspect that Capybara is looking at the initial state of the page (invisible in this case), evaluating the state of the DOM and failing the test before the JS runs.

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

Yes, I set the :js => trueon the containing describe block :)

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

Any ideas would be greatly appreciated! I'm hoping I don't have to put an intentional delay in here, that feels flaky and will slow things down.

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

回答by Jon M

I think that the findstatement here is the one with the implicit wait, so Capybara will wait until the element is on the page, but won't wait for it to become visible.

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

Here, you would want Capybara to wait for the visible element to appear, which should be achievable by specifying the visibleoption:

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

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

I haven't tried it, but the ignore_hidden_elementsconfiguration option might be useful here as well, if you wanted findto always wait for visible elements.

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

回答by Bj?rn Grossmann

This is another way to do it that works perfectly fine for me:

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

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

Especially for more complex finds, such as

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

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

which would assert that an element has been hidden.

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

回答by Zubin

If you want to check that an element is on the page but is not visible, visible: falsewon't work as you might expect. Had me stumped for a bit.

如果您想检查某个元素是否在页面上但不可见,visible: false则不会像您预期的那样工作。让我难住了一会儿。

Here's how to do it:

这是如何做到的:

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

回答by Jignesh Gohel

Using:

使用:

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

I have a Rails application in which there is a link which when clicked should submit an AJAX post request and return a JS response.

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

Link code:

链接代码:

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

The JS response (.js.haml file) should toggle the following hidden div on the page the link exists:

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

 #notification_status(style='display:none')

js.haml file contents:

js.haml 文件内容:

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

I was testing my scenario of sending notification and displaying the notification status message to the user using Cucumber (cucumber-rails gem with built in Capybara support)

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

I was trying to test that the element having id: notification_statuswas visible on successful response in my step definition.For this I tried following statements:

我试图测试具有 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)

Neither of above worked for me and failed my step.Out of the above listed 5 snippets the last 4 failed with following error:

以上都没有对我来说有效并且我的步骤失败了。在上面列出的 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)'

which was strange because following statement was passing correctly:

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

page.has_selector?('#notification_status')

And in fact I inspected the page source using

事实上,我使用

  print page.html

which showed up

出现了

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

which was expected.

这是预料之中的。

Finally I found this link capybara assert attributes of an elementwhich showed up how to inspect an element's attribute in raw manner.

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

Also I found in Capybara documentation for visible? method (http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method) following information:

我还在 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.

Thus I came to the conclusion that when testing visibility of an element do not rely on results of Capybara's visible? method when using a CSS selector and using the solution suggested in link capybara assert attributes of an element

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

I came up with following:

我想出了以下内容:

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

 World(CustomMatchers)

Usage:

用法:

should_be_visible('#notification_status')

回答by smallsense

You might want to look at this post, which gives a sample method for waiting until all ajax requests are complete:

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

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

回答by Alex Foxleigh

The accepted answer is a bit outdated now as 'should' is deprecated syntax. These days you'd be better off doing something along the lines of expect(page).not_to have_css('#blah', visible: :hidden)

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

回答by Dono

The other answers on here are the best way to "wait" for the element. However I have found this didn't work for the site I am working on. Basically the element that needed clicking was visible before the function behind that was fully loaded. This is in fractions of a second but I found my test ran so quick on occasion that it clicked the button and nothing happened. I managed to work around it by doing this make-shift boolean 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

Basically it uses the capybara default wait time to look for something that should appear, if it isnt there it will retry your click.

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

Again I will say that the should have_selectormethod should be tried first but if it just wont work try this

我再说一遍,should have_selector应该先尝试该方法,但如果它不起作用,请尝试此方法