1
0
Fork 0
mirror of https://github.com/teamcapybara/capybara.git synced 2022-11-09 12:08:07 -05:00
teamcapybara--capybara/lib/capybara/server/middleware.rb
Blake Williams 772ddc831c Fix middleware request uri race condition
When writing a new Rails system test I ran into an issue where the
browser would hang and not close, eventually failing the test due to
pending requests. There were no clear pending requests and the requests
mentioned were AJAX calls that should have been made several pages ago.

I believe the cause is an AJAX call being cancelled almost immediately
after it was initiated, but I'm not 100% positive.

Code wise, it looks like the value of `env['REQUEST_URI']` that
increments the counter is different from the `env['REQUEST_URI']` that's
decremented in the `ensure` block.

This resolves the issue by storing the `env['REQUEST_URI']` value in a
variable so it will be consistent between counter calls.
2020-08-06 23:04:17 -04:00

71 lines
1.5 KiB
Ruby

# frozen_string_literal: true
module Capybara
class Server
class Middleware
class Counter
def initialize
@value = []
@mutex = Mutex.new
end
def increment(uri)
@mutex.synchronize { @value.push(uri) }
end
def decrement(uri)
@mutex.synchronize { @value.delete_at(@value.index(uri) || @value.length) }
end
def positive?
@mutex.synchronize { @value.length.positive? }
end
def value
@mutex.synchronize { @value.dup }
end
end
attr_reader :error
def initialize(app, server_errors, extra_middleware = [])
@app = app
@extended_app = extra_middleware.inject(@app) do |ex_app, klass|
klass.new(ex_app)
end
@counter = Counter.new
@server_errors = server_errors
end
def pending_requests
@counter.value
end
def pending_requests?
@counter.positive?
end
def clear_error
@error = nil
end
def call(env)
if env['PATH_INFO'] == '/__identify__'
[200, {}, [@app.object_id.to_s]]
else
request_uri = env['REQUEST_URI']
@counter.increment(request_uri)
begin
@extended_app.call(env)
rescue *@server_errors => e
@error ||= e
raise e
ensure
@counter.decrement(request_uri)
end
end
end
end
end
end