自升级到Capybara 2.4以来,我一直在遇到这个问题。以前,这个块运行良好:
page.document.synchronize do
page.should have_no_css('#ajax_indicator', :visible => true)
end
这意味着在继续下一步之前强行等待ajax指示消失。
由于上面的内容返回RSpec::Expectations::ExpectationNotMetError
,因此同步不会重新运行该块,而只是抛出错误。不知道为什么这个在我之前使用的版本中工作(我相信2.1)。
synchronize
块仅重新运行返回以下内容的块:
Capybara::ElementNotFound
Capybara::ExpectationNotMet
无论某个驱动程序添加到该列表中。
请参阅Justin的回复,了解更全面的解释和不使用synchronize
的示例,或查看我对直接解决方案的回复。
答案 0 :(得分:3)
have_no_css
匹配器已经等待元素消失。问题似乎是在synchronize
块内使用它。 synchronize
方法仅针对某些例外重新运行,但不包括RSpec::Expectations::ExpectationNotMetError
。
删除synchronize
似乎可以做你想要的 - 即强制等待直到元素消失。换句话说,就是这样做:
page.should have_no_css('#ajax_indicator', :visible => true)
工作示例
这是一个页面,比如说“wait.htm”,我认为它会重现你的问题。它有一个链接,当点击时,等待6秒,然后隐藏指标元素。
<html>
<head>
<title>wait test</title>
<script type="text/javascript" charset="utf-8">
function setTimeoutDisplay(id, display, timeout) {
setTimeout(function() {
document.getElementById(id).style.display = display;
}, timeout);
}
</script>
</head>
<body>
<div id="ajax_indicator" style="display:block;">indicator</div>
<a id="hide_foo" href="#" onclick="setTimeoutDisplay('ajax_indicator', 'none', 6000);">hide indicator</a>
</body>
</html>
以下规范显示,通过使用page.should have_no_css
而无需手动调用synchronize
,Capybara已经迫使等待。等待仅2秒时,规范失败,因为元素不会消失。当等待10秒时,规格通过,因为元素有时间消失。
require 'capybara/rspec'
Capybara.run_server = false
Capybara.current_driver = :selenium
Capybara.app_host = 'file:///C:/test/wait.htm'
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = [:should, :expect]
end
end
RSpec.describe "#have_no_css", :js => true, :type => :feature do
it 'raise exception when element does not disappear in time' do
Capybara.default_wait_time = 2
visit('')
click_link('hide indicator')
page.should have_no_css('#ajax_indicator', :visible => true)
end
it 'passes when element disappears in time' do
Capybara.default_wait_time = 10
visit('')
click_link('hide indicator')
page.should have_no_css('#ajax_indicator', :visible => true)
end
end
答案 1 :(得分:1)
从Capybara 2.0版本开始,您可以自定义内联等待时间参数,将其传递给#have_no_css
方法:
page.should have_no_css('#ajax_indicator', visible: true, wait: 3)
答案 2 :(得分:-1)
我已解决的解决方案如下:
page.document.synchronize do
page.assert_no_selector('#ajax_indicator', :visible => true)
end
assert_no_selector
方法正确抛出Capybara::ExpectationNotMet
错误,似乎与has_no_css
的工作方式相同,因此我对此解决方案感到满意。
我仍然不知道为什么某些方法会抛出RSpec错误而不是其他方法。