Skip to content

Instantly share code, notes, and snippets.

@robhurring
Last active January 21, 2016 23:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robhurring/bc9978844680587197a4 to your computer and use it in GitHub Desktop.
Save robhurring/bc9978844680587197a4 to your computer and use it in GitHub Desktop.
Capybara + Angular.js wait_for_ajax
require 'selenium-webdriver'
module FeatureHelpers
DEFAULT_WAIT_TIME = 30
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app,
inspector: true,
js_errors: true,
timeout: DEFAULT_WAIT_TIME
)
end
Capybara.default_wait_time = DEFAULT_WAIT_TIME
Capybara.javascript_driver = :poltergeist_debug
# Public: Block until our page says there are no requests currently
# in progress, or we timeout.
#
# max_wait - The amount of time you're willing to wait for AJAX to complete.
# check_pause - The amount of time between checks
# notify_after_ticks - After this many ticks output a message about whats going on.
#
# Returns nothing.
def wait_for_ajax(max_wait = Capybara.default_wait_time, check_pause = 0.1, notify_after_ticks = 10)
ticks = 0
new_line = false
Timeout.timeout(max_wait) do
until finished_all_ajax_requests?
ticks += 1
if (ticks % notify_after_ticks).zero?
wait_time = (ticks * check_pause.to_f).round(1)
debug_inplace("[waiting <time: #{wait_time}s/#{max_wait}s>] #{last_ajax_request}\r#{eol}")
new_line = true
end
sleep check_pause
end
end
puts if new_line # flush line
end
private
def debug_inplace(message)
$stderr.write("%s\r" % message)
$stderr.flush
end
# Private: The URL of the last active AJAX request.
# Returns the URL if present, blank string otherwise.
def last_ajax_request
page.evaluate_script('window.__lastActiveRequest__').to_s
end
# Private: The number of AJAX requests currently in progress on the page.
# Returns the number of active requests.
def current_active_requests
page.evaluate_script('window.__activeRequests__')
end
# Private: Check if we have no AJAX request in progress.
# Returns false if there are active requests, true otherwise.
def finished_all_ajax_requests?
current_active_requests.zero?
end
end
RSpec.configure do |config|
config.include FeatureHelpers, type: :feature
end
(function(module) {
'use strict';
// Track HTTP requests so we can fix capybara specs without resorting
// to random sleeps.
// See: spec/support/feature_helpers.rb for how its used
module.config(['$httpProvider',
function($httpProvider) {
var key = '__activeRequests__';
var lastUrl = '__lastActiveRequest__';
$httpProvider.interceptors.push(['$window', '$q',
function($window, $q) {
$window[key] = 0;
var startRequest = function(config) {
$window[key] += 1;
$window[lastUrl] = config.method + ' ' + config.url;
};
var finishRequest = function() {
$window[key] -= 1;
if($window[key] < 0) {
$window[key] = 0;
}
};
return {
request: function(config) {
startRequest(config);
return config;
},
requestError: function(rejection) {
finishRequest();
return $q.reject(rejection);
},
response: function(response) {
finishRequest();
return response;
},
responseError: function(rejection) {
finishRequest();
return $q.reject(rejection);
}
};
}
]);
}
]);
})(angular.module('MyModule'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment