Capybara: Quick checking for element presence (without retries or timeout)

Updated . Posted . Visible to the public.

Element finding is a central feature of Capybara. Since #find is normally used to get elements from the current page and interact with them, it's a good thing that some Capybara drivers (e.g. Selenium) will wait an amount of time until the expected element shows up. But if Capybara cannot #find it at all, you'll get an error.

if page.find('.that-element')
  # Do something
else
  # Never happens because #find raises
end

In order to simply check whether an element is present, without errors raised, you can use #has_css?. It will return a Boolean – but will wait as well. If the element does not exist, it will take the configured Capybara.default_max_wait_time for this check to return false, which is usually several seconds.

The same goes for the other direction and for #all:

  • has_no_css? returns true as soon as the element is gone, but false only after the full wait time if the element is there.
  • Since Capybara 3, all waits for a first match, so all('.that-element').empty? takes the full wait time whenever nothing matches.

In a shared helper that branches on the state of the page, this quickly adds up to minutes per test run.

The solution is to disable the waiting for just that check:

if page.has_css?('.that-element', wait: 0)
  # Do something
else
  # Do something else
end

page.has_no_css?('.that-element', wait: 0)
page.all('.that-element', wait: false).empty?

Important

If you opt-out of Capybara's retry mechanism you need to retry yourself or your test will be flaky.

..or use a pre-existing matcher depending on your use case:

expect(page).to have_no_css('.that-element')        # ✅ returns as soon as the element is gone 
expect(page.has_css?('.that-element')).to eq(false) # ❌ waits the full time whenever it passes

Note the wait: 0 argument. Actually there is a host of options Show archive.org snapshot worth knowing (scroll down to the "Options Hash" section).

Profile picture of Dominik Schöler
Dominik Schöler
Last edit
Michael Leimstädtner
License
Source code in this card is licensed under the MIT License.
Posted by Dominik Schöler to makandra dev (2019-07-01 13:40)