Where developers come to connect, share, build and be inspired.

9

Wait for ajax with capybara 2.0

10652 views


Since they removed wait_until from capybara 2.0 I had to work out a different way to wait for all the ajax requests in a test to finish.

This need comes since we have a backbone application and many of the ajax requests executed won't have direct side effects on the DOM.

So the solution looks like this:

def wait_for_ajax
  Timeout.timeout(Capybara.default_wait_time) do
    active = page.evaluate_script('jQuery.active')
    until active == 0
      active = page.evaluate_script('jQuery.active')
    end
  end
end

Comments

  • 5009d470b40e5f3aefb5515559c8745d

    Thanks for share. I would like to add my 2 cents with a DRY version of your code.

    def wait_for_ajax
      Timeout.timeout(Capybara.default_wait_time) do
        loop do
          active = page.evaluate_script('jQuery.active')
          break if active == 0
        end
      end
    end
    
  • D4d312a34cfa93a577373558f8c34da8

    actually, not sure if this is necessary, see http://www.elabs.se/blog/53-why-wait_until-was-removed-from-capybara

  • User-avatar

    Good solution, thanks!

  • 483f1b98648c3e9b2c75fb6bb7ad2ed9

    Where exactly do you add this?

  • 84687433fbeed3d44d0298b7032f9780

    @dejancancarevic just add this in your spec_helper.rb

  • D4d312a34cfa93a577373558f8c34da8

    does this work for Selenium? I got a:

    Failure/Error: wait_for_ajax
         Capybara::NotSupportedByDriverError:
           Capybara::Driver::Base#evaluate_script
    

    after putting it in my spec_helper.rb

  • 84687433fbeed3d44d0298b7032f9780

    @mswieboda, I don't know why you would get such error. I normally use phantomjs but sometimes selenium. In my project I have selenium-webdriver (2.38.0) just in case

    An regarding your second command. We use this helper only in some special cases, normally you should check for DOM changes

  • 3915eeaee91d96525e3e4e0fcdf93343

    I found this through thoughbot's blog. Here are some minor changes I made (from their version). In the application I'm testing the AJAX requests are potentially long. I've added the ability to set a custom wait time AND to ensure that jQuery is defined before calling jQuery.active

      # @see http://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara Automatically wait for AJAX with Capybara
      def finished_all_ajax_requests?
        return_value = page.evaluate_script <<-SCRIPT.strip.gsub(/\s+/,' ')
          (function () {
            if (typeof jQuery != 'undefined') {
              return jQuery.active;
            }
            else {
              console.log("Failed on the page: " + document.URL);
              console.error("An error occurred when checking for `jQuery.active`.");
            }
          })()
        SCRIPT
        return_value and return_value.zero?
      end
    
      # @see http://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara Automatically wait for AJAX with Capybara
      def wait_for_ajax(task: 'Waiting for AJAX', wait_time: nil)
        DebugHelpers.time_execution(task) do
          wait_time ||= Capybara.default_wait_time
    
          Timeout.timeout(wait_time) do
            loop until finished_all_ajax_requests?
          end
        end
      end
    
  • 7dc31177af267cbf69ced5b8d59e33c9

    Good solution, thanks! Lexia 3

  • None

    Thanks for this. Of the various suggestions I found at stack overflow and elsewhere, this was the only one which worked (Rails 4.1, RSpec 2.14, Capybara Webkit 1.3).

Add a comment