How to Make Capybara Check for Visibility After Some Js Has Run

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

I think that the find statement 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.

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

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

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

how to test window.status variable

With Capybara when you want to get access to the values of JS things you use evaluate_script. In this case that would mean

evaluate_script('window.status')

If you want to wait for that be some value you could wrap it in a loop (possibly with a timeout), or if you just want to verify it is a specific value right now

expect(evaluate_script('window.status')).to eq 'ready_to_print'

Capybara: How to check that an element has content among many similar elements?

Apparently you can select elements with a given text:

page.should have_selector('h2', text: /#{headline}/i)

Note: I used a regular expression to make the text search case insensitive.

Capybara synchronize with has_no_css?

The have_no_css matcher already waits for the element to disappear. The problem seems to be using it within a synchronize block. The synchronize method only re-runs for certain exceptions, which does not include RSpec::Expectations::ExpectationNotMetError.

Removing the synchronize seems to do what you want - ie forces a wait until the element disappears. In other words, just do:

page.should have_no_css('#ajax_indicator', :visible => true)

Working Example

Here is a page, say "wait.htm", that I think reproduces your problem. It has a link that when clicked, waits 6 seconds and then hides the indicator element.

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

The following spec shows that by using the page.should have_no_css without manually calling synchronize, Capybara is already forcing a wait. When waiting only 2 seconds, the spec fails since the element does not disappear. When waiting 10 seconds, the spec passes since the element has time to disappear.

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

Rails4/Capybara - use the value of the test window width/dimensions inside a test

You shouldn't be using driver specific methods for any of this (any time you're using Capybara.current_session.driver. you're probably doing something wrong). Rather you should be using Capybara's window api - http://www.rubydoc.info/gems/capybara/Capybara/Window

To get the size of the current window

Capybara.current_session.current_window.size

To set the size of the current window

Capybara.current_session.current_window.resize_to(width, height)

Link doesn't hide after some time capybara

There are a number of things wrong with your approach to testing this. The reason your attempt is failing is because using_wait_time just sets the amount of time Capybaras matchers will wait for their expectations to become true, it doesn't actually make the program wait. Therefore expect(page).to have_no_css('.comment-edit') will wait up to the time your using_wait_time specifies, rechecking the page every 50 milliseconds or so for the content, but it never reloads the page and doesn't wait before the loading the page. For your approach to work you would need to sleep before visiting the page

it 'hides the edit symbol due 5 minutes after comment was created' do
sleep 5.minutes
visit category_theme_path(category, theme)
save_and_open_page
expect(page).to have_no_css('.comment-edit')
end

however this is a terrible idea since your tests will become ridiculously slow.

Rather than that approach you could be generating your test comment already "old" (as pascal betz suggests), using something like FactoryGirl and specifying a created_at that is more than 5 minutes ago.

FactoryGirl.create(:comment, created_at: 5.minutes.ago)

or if you want to continue creating your comment through the interface then include something like the Timecop gem and you can do

 Timecop.travel(5.minutes.from_now) do
visit category_theme_path(category, theme)
save_and_open_page
expect(page).to have_no_css('.comment-edit')
end

which will move the clock 5 minutes forward before visiting the page, and then reset it back to normal once the block if finished.

Additionally, your editable? method is comparing in the wrong direction and should be

def editable?
self.created_at > (Time.now - 5.minute)
end

Then the view should be

- if comment.editable?
= link_to 'Edit', edit_category_theme_comment_path(@category, @theme, comment)


Related Topics



Leave a reply



Submit