BigW Consortium Gitlab

Commit 645a55f1 by Rémy Coutable

Introduce a new middleware for the test environment that can block requests

The idea is that after each feature spec example, we block all incoming requests at the Rack level, go to the 'about:blank' page, and wait until the current requests reach 0. This should solve the problem where a request would end after database cleaner performed the database truncation. The problem was that a GET request can still lead to records creation (e.g. namespaces or routes). Signed-off-by: 's avatarRémy Coutable <remy@rymai.me>
parent 3574963b
...@@ -327,6 +327,7 @@ group :test do ...@@ -327,6 +327,7 @@ group :test do
gem 'test_after_commit', '~> 1.1' gem 'test_after_commit', '~> 1.1'
gem 'sham_rack', '~> 1.3.6' gem 'sham_rack', '~> 1.3.6'
gem 'timecop', '~> 0.8.0' gem 'timecop', '~> 0.8.0'
gem 'concurrent-ruby', '~> 1.0.5'
end end
gem 'octokit', '~> 4.6.2' gem 'octokit', '~> 4.6.2'
......
...@@ -128,7 +128,7 @@ GEM ...@@ -128,7 +128,7 @@ GEM
execjs execjs
coffee-script-source (1.10.0) coffee-script-source (1.10.0)
colorize (0.7.7) colorize (0.7.7)
concurrent-ruby (1.0.4) concurrent-ruby (1.0.5)
connection_pool (2.2.1) connection_pool (2.2.1)
crack (0.4.3) crack (0.4.3)
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
...@@ -868,6 +868,7 @@ DEPENDENCIES ...@@ -868,6 +868,7 @@ DEPENDENCIES
chronic (~> 0.10.2) chronic (~> 0.10.2)
chronic_duration (~> 0.10.6) chronic_duration (~> 0.10.6)
coffee-rails (~> 4.1.0) coffee-rails (~> 4.1.0)
concurrent-ruby (~> 1.0.5)
connection_pool (~> 2.0) connection_pool (~> 2.0)
creole (~> 0.5.0) creole (~> 0.5.0)
d3_rails (~> 3.5.0) d3_rails (~> 3.5.0)
......
Rails.application.configure do Rails.application.configure do
# Make sure the middleware is inserted first in middleware chain
config.middleware.insert_before('ActionDispatch::Static', 'Gitlab::Testing::RequestBlockerMiddleware')
# Settings specified here will take precedence over those in config/application.rb # Settings specified here will take precedence over those in config/application.rb
# The test environment is used exclusively to run your application's # The test environment is used exclusively to run your application's
......
# rubocop:disable Style/ClassVars
# This is inspired by http://www.salsify.com/blog/engineering/tearing-capybara-ajax-tests
# Rack middleware that keeps track of the number of active requests and can block new requests.
module Gitlab
module Testing
class RequestBlockerMiddleware
@@num_active_requests = Concurrent::AtomicFixnum.new(0)
@@block_requests = Concurrent::AtomicBoolean.new(false)
# Returns the number of requests the server is currently processing.
def self.num_active_requests
@@num_active_requests.value
end
# Prevents the server from accepting new requests. Any new requests will return an HTTP
# 503 status.
def self.block_requests!
@@block_requests.value = true
end
# Allows the server to accept requests again.
def self.allow_requests!
@@block_requests.value = false
end
def initialize(app)
@app = app
end
def call(env)
increment_active_requests
if block_requests?
block_request(env)
else
@app.call(env)
end
ensure
decrement_active_requests
end
private
def block_requests?
@@block_requests.true?
end
def block_request(env)
[503, {}, []]
end
def increment_active_requests
@@num_active_requests.increment
end
def decrement_active_requests
@@num_active_requests.decrement
end
end
end
end
...@@ -35,6 +35,7 @@ RSpec.configure do |config| ...@@ -35,6 +35,7 @@ RSpec.configure do |config|
config.include Warden::Test::Helpers, type: :request config.include Warden::Test::Helpers, type: :request
config.include LoginHelpers, type: :feature config.include LoginHelpers, type: :feature
config.include SearchHelpers, type: :feature config.include SearchHelpers, type: :feature
config.include WaitForRequests, :js
config.include WaitForAjax, type: :feature config.include WaitForAjax, type: :feature
config.include StubConfiguration config.include StubConfiguration
config.include EmailHelpers, type: :mailer config.include EmailHelpers, type: :mailer
......
module WaitForRequests
extend self
# This is inspired by http://www.salsify.com/blog/engineering/tearing-capybara-ajax-tests
def wait_for_requests_complete
stop_client
Gitlab::Testing::RequestBlockerMiddleware.block_requests!
wait_for('pending AJAX requests complete') do
Gitlab::Testing::RequestBlockerMiddleware.num_active_requests.zero?
end
ensure
Gitlab::Testing::RequestBlockerMiddleware.allow_requests!
end
# Navigate away from the current page which will prevent any new requests from being started
def stop_client
page.execute_script %Q{
window.location = "about:blank";
}
end
# Waits until the passed block returns true
def wait_for(condition_name, max_wait_time: Capybara.default_max_wait_time, polling_interval: 0.01)
wait_until = Time.now + max_wait_time.seconds
loop do
break if yield
if Time.now > wait_until
raise "Condition not met: #{condition_name}"
else
sleep(polling_interval)
end
end
end
end
RSpec.configure do |config|
config.after(:each, :js) do
wait_for_requests_complete
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment