bkunzi01 bkunzi01 - 6 months ago 100
Ruby Question

How to get poltergeist/PhantomJS to delay returning the page to Capybara until AJAX is loaded?

How do I keep PhantomJS from returning the page to Capybara for several seconds to allow AJAX to finish loading? The HTML body I am getting back is:

<!--div class='loading'>PLEASE WAIT WHILE PAGE LOADS</div-->


Which is telling me that PhantomJS returned the page before the page finished loading its AJAX assets. Is there any way I can slow this down? I've tried using the rasterize.js solution but it looks as though any script I add to poltergeist's "phantomjs_options" hash is overlooked.

Answer

Using a Capybara method that waits for you, assert that content is on the page that should exist on the page only after AJAX has completed. For example, if the page should say "Page loaded!" only after AJAX has completed, and assuming you're using RSpec, do this:

expect(page).to have_content("Page loaded!")

You can then safely test other things on the page that depend on AJAX having completed.

Capybara methods that wait for specified content to appear include find and find_* methods, within, has_content?/has_no_content?, has_css?/has_no_css?, has_selector?/has_no_selector?, click_*, fill_in, check, uncheck, select and choose. Some Capybara methods don't wait, including current_path, visit, execute_script, evaluate_script and node accessors like text and value. all and first wait if you give them options that give them something specific to wait for (:count, :minimum, :maximum, :between), otherwise they don't. It's quite a minefield. (I took the lists mostly from this blog post.)

There are other ways to wait (sleep (bad), polling the database until a change caused by AJAX appears, etc.) but using Capybara methods that wait for you is the usual and recommended way.