I have a Rails integration test that's failing, and I can't figure out why. I'm using Capybara with Selenium as the driver.
The test checks that page content has been removed after an AJAX call takes place. The relevant action is that a button is clicked, and that button click causes a section of the page to be removed via a jQuery remove()
call. Here's an approximation of the integration testing code:
click_button("Remove stuff")
assert has_no_link?("This should be removed")
The assertion fails, implying that the link still exists.
I've been reading up on Capybara, and I know that you can extend the default wait time. I've extended it to a ridiculous value (20 seconds), and still the assertion fails.
When I follow the test process myself manually, the source of the page still shows the content, but the DOM does not (by viewing Firefox's DOM Inspector and looking for the element). Is this the issue? I've even tried inspecting the DOM while the tests are running in Firefox to check if the content was there, and it doesn't appear to be.
I have no idea how Capybara is still finding this link that no longer exists in the DOM. Is Capybara examining the source instead of the DOM and finding the link there? If so, I have no idea how to fix this test to make sure that the test passes. Refreshing the page would fix the issue, but that's not exactly what a user would do, so I hesitate to change the page just to make the test pass...
Would love any recommendations on how to approach this problem.
Thanks!
Thoughtbot has a great blog post on waiting for AJAX, which you can read here, though it is based on Rspec, and it looks like you are using TestUnit.
It works great for situations when Capybara doesn't quite wait long enough, but doesn't add unnecessarily long timeouts. I work mostly in Rspec now, but I think you can modify it by doing this:
# Create this file in test/support/wait_for_ajax.rb
module WaitForAjax
def wait_for_ajax
Timeout.timeout(Capybara.default_max_wait_time) do
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script('jQuery.active').zero?
end
end
You can either include it when needed in the individual test file, or use one of the strategies provided in this SO post for automatically including it every time.
Then, whenever you have a test that is not properly waiting for AJAX to finish, just insert the line wait_for_ajax
. Using your code as an example:
click_button("Remove stuff")
wait_for_ajax
assert has_no_link?("This should be removed")
there was some method called wait_until, but it was deprecated recently and changed with synchronize method.
http://www.elabs.se/blog/53-why-wait_until-was-removed-from-capybara
https://github.com/jnicklas/capybara/blob/master/lib/capybara/node/base.rb#L44
For now I don't know how to use it exactly, but I'm waiting for answer for my question from the author, so I hope to resolve this problem soonly
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With