WaitsDoes not Wait
find(“#foo”)Calling an attribute (like .text on an element after it has been found)

The most important Capybara feature you must know is this:

Capybara automatically waits for elements to appear or disappear on the page.

Try a command like:


This will block (or wait) until an element with id “foo” appears on the page.

Other Capybara selectors that wait are  has_content?("bar")click_link("baz") and most other things you can do with Capybara.

Let’s look at a more complicated case:


Even if #foo is originally on the page and then removed and replaced with a #foo which contains baz after a short wait, Capybara will still figure this out. Let’s make that really clear, Capybara is very good at waiting for content.

Generally speaking, this behavior is completely transparent. You don’t even really have to think about it, because Capybara just does it for you. What trips a lot of people up is that they try to do something like this:

page.find("foo").text.should contain("login failed")

And now they have introduced potential timing issues. text, being just a regular method, which returns a regular string, isn’t going to sit around and wait for anything. It will simply return the text as it appears when Capybara gets to this line and call it a day.

When Things Get Hairy

How Much Do I Personally Hate XPath

You might love Xpath and if you do more power to you. I personally cannot stand it, nor can I stand having to thinking about another syntax. There, I generally find myself using CSS selectors, button selectors, and within blocks a lot.

Only Test The UI, Except When You Can’t

Watch out for animations

Capybara and Animate on Scroll

Watch out for the Animate-on-Scroll library, which has become more popular with modern marketing-driven websites.

If you use it, you’ll find yourself wanting to scroll to the element on the page to make sure it appears.

But there’s a terrible catch: You can’t scroll to an element if that element itself is hidden by AOS, or if it is inside something that is hidden by AOS. That means you must wrap the things that will as appear-on-scroll inside of empty wrapping elements which 1) targetable using CSS or Xpath selectors, etc, and 2) are not themselves hidden when the page loads.

You’ll want to scroll to that thing first, then use one of the waiting-style finders (see the left column in the list above).

Watch out for your window size

Selenium Chrome vs. Selenium Chrome Headless

Sometimes you need to debug the same spec in both the headless driver and the selenium driver. This is extremely tedious. A naive approach might think, why not just stick to one or the other. The problem, is without seeing the UI, it’s often very difficult to debug the test at all, so you find yourself switching back and forth between the headless driver and the selenium driver.

But, sometimes, the test itself behaves differently between the two drivers, making this task the most complicated part of Ruby development.