Created
September 18, 2014 20:48
-
-
Save tonyhb/dfd8da6522b93a45e377 to your computer and use it in GitHub Desktop.
RackRequestCounter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/support/click.rb | |
module Capybara | |
module Node | |
class Element < Base | |
# Override the default implementation of click so that whenever we click | |
# on something, we also wait for any ajax requests to finish. | |
def click | |
synchronize { base.click } | |
wait_for_ajax | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/rack_request_counter.rb | |
# | |
# Source, which use jruby and atomic: | |
# http://blog.salsify.com/engineering/tearing-capybara-ajax-tests | |
# https://gist.githubusercontent.com/jturkel/9317269/raw/rack_request_blocker.rb | |
# Rack middleware that keeps track of the number of active requests and can block new requests. | |
class RackRequestCounter | |
@@num_active_requests = 0 | |
@@nil_requests_at = Time.now | |
def self.reset | |
@@nil_requests_at = Time.now | |
@@num_active_requests = 0 | |
end | |
# Returns the number of requests the server is currently processing. | |
def self.num_active_requests | |
@@num_active_requests | |
end | |
def self.nil_requests_at | |
@@nil_requests_at | |
end | |
# 503 status. | |
def initialize(app) | |
@app = app | |
end | |
def call(env) | |
puts "Hit: #{env["PATH_INFO"]}" if ENV["SHOW_URLS"] | |
increment_active_requests | |
@app.call(env) | |
ensure | |
decrement_active_requests | |
end | |
private | |
def increment_active_requests | |
@@num_active_requests += 1 | |
end | |
def decrement_active_requests | |
@@num_active_requests -= 1 | |
# Mark this as the last time there were zero requests | |
@@nil_requests_at = Time.now if @@num_active_requests == 0 | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/support/wait_for.rb | |
# | |
# Coupled with a Ruby-side request counter: see /lib/rack_request.counter.rb | |
class Capybara::Session | |
def wait_until(timeout = Capybara.default_wait_time) | |
Timeout.timeout(timeout) do | |
sleep(0.05) until value = yield | |
value | |
end | |
end | |
end | |
# If this is called in a scenario from rspec page will be defined. However, | |
# we've also overridden Capybara's default 'click' behaviour to also call | |
# wait_for_ajax; this means we need to load the current session from Capybara. | |
def wait_for_ajax(timeout = Capybara.default_wait_time) | |
page ||= Capybara.current_session | |
# After clicking, wait 50ms for an ajax request to fire off | |
sleep(0.05) | |
page.wait_until(timeout) do | |
# If there are no active requests and the last request was over 150ms ago, | |
# continue. This means that one AJAX request wasn't depending on another to | |
# finish... race condition central.com | |
RackRequestCounter.num_active_requests <= 0 && Time.now - RackRequestCounter.nil_requests_at > 0.15 | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment