Reputation: 6246
I am frequently running into issues in capybara with request tests failing because capybara is not waiting for ajax events to complete before moving on.
Google seems to indicate I should be using :resynchronize option for my tests to fix this. But it is not working.
To prove this is an issue, failing tests can be fixed by putting a sleep statement after the ajax call. This seems hacky any bad practice as the appropriote delay will vary depending on the speed of the machine running the tests. And picking a suitably large value will seriously slow down running a test suite with lots of ajax actions.
An example of a failing / passing test is below. The sleep before clicking on save makes the difference between passing / failing on page.should have_content('custom item'):
it "should be able create a new todo item", :js, :resynchronize, :focus do
# Visit new action
visit new_todo_list
# Fill in the name
fill_in "#name", "test list"
# Click on add item to launch inline popup
find('a.add-item').click
within '#new_item' do
fill_in 'todo_item_description', :with => 'custom item'
# Run ajax action to add currrent item
find('.btn').click
end
sleep(1)
# Save
find('a.save').click
page.should have_content('test list')
page.should have_content('custom item')
end
Is this a bug in capybara or am I doing something wrong?
Thanks for any help...
Upvotes: 2
Views: 1737
Reputation: 27374
I had issues with this a while back, and used this approach to figure out when the ajax requests are done:
wait_until do
page.evaluate_script('$.active') == 0
end
Still pretty hacky, but slightly better than using sleep
. I got it from here. I'm using it for Cucumber features but it should work in rspec request specs as well.
Update (6/19/2013)
wait_until
was removed from Capybara in version 2.0, see: Why wait_until was removed from Capybara for details on why.
I've followed one of the suggestions and implemented it anyway, just for this one case (which I think is justified):
def wait_until
require "timeout"
Timeout.timeout(Capybara.default_wait_time) do
sleep(0.1) until value = yield
value
end
end
Upvotes: 4