In the code below, if I have the sleep 1, the test passes. Without the sleep, the test reliably fails. Calling hover on the_image triggers the ajax. Maybe I’m setting up the last expect incorrectly? Or are there cases where sleep is needed?
In general you should not have to add explicit sleep calls in capybara feature specs as it has built in logic for waiting for ajax requests, and retrying find and has_content calls within a given period of time. You can read up on the specifics of this in the Async & AJAX section of the docs.
That said, it looks like you are using the expected methods, ie find and have_xpath, which should activate this waiting logic. With that in mind, you might want to try bumping up the overall Capybara wait timeout setting:
# in spec/spec_helper.rb
Capybara.default_wait_time = 3 # default is 2
Whereas sleep 1 is guaranteed to add 1 sec to your spec run time, bumping Capybara’s timeout threshold will only use as much time as needed.
Chris is right : find will wait. However, you’re only calling find for the link. Is it possible the selector for that link is present before the href attribute is populated with a value that will match?