Commit d4a91967 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Use transactions in JS feature specs

Uses Rails transactional tests instead of DatabaseCleaner
transaction strategy because that doesn't work with JS tests
parent ecffca5d
...@@ -40,7 +40,7 @@ Rails.application.configure do ...@@ -40,7 +40,7 @@ Rails.application.configure do
# Print deprecation notices to the stderr # Print deprecation notices to the stderr
config.active_support.deprecation = :stderr config.active_support.deprecation = :stderr
config.eager_load = false config.eager_load = true
config.cache_store = :null_store config.cache_store = :null_store
......
# frozen_string_literal: true
ActiveRecord::ConnectionAdapters::ConnectionPool.prepend Gitlab::Patch::ActiveRecordQueryCache
...@@ -284,17 +284,28 @@ module Gitlab ...@@ -284,17 +284,28 @@ module Gitlab
end end
# inside_transaction? will return true if the caller is running within a transaction. Handles special cases # inside_transaction? will return true if the caller is running within a transaction. Handles special cases
# when running inside a test environment, in which the entire test is running with a DatabaseCleaner transaction # when running inside a test environment, where tests may be wrapped in transactions
def self.inside_transaction? def self.inside_transaction?
if Rails.env.test?
ActiveRecord::Base.connection.open_transactions > open_transactions_baseline ActiveRecord::Base.connection.open_transactions > open_transactions_baseline
else
ActiveRecord::Base.connection.open_transactions > 0
end
end end
def self.open_transactions_baseline # These methods that access @open_transactions_baseline are not thread-safe.
if ::Rails.env.test? # These are fine though because we only call these in RSpec's main thread. If we decide to run
return DatabaseCleaner.connections.count { |conn| conn.strategy.is_a?(DatabaseCleaner::ActiveRecord::Transaction) } # specs multi-threaded, we would need to use something like ThreadGroup to keep track of this value
def self.set_open_transactions_baseline
@open_transactions_baseline = ActiveRecord::Base.connection.open_transactions
end end
0 def self.reset_open_transactions_baseline
@open_transactions_baseline = 0
end
def self.open_transactions_baseline
@open_transactions_baseline ||= 0
end end
private_class_method :open_transactions_baseline private_class_method :open_transactions_baseline
......
# frozen_string_literal: true
# Fixes a bug where the query cache isn't aware of the shared
# ActiveRecord connection used in tests
# https://github.com/rails/rails/issues/36587
# To be removed with https://gitlab.com/gitlab-org/gitlab-ce/issues/64413
module Gitlab
module Patch
module ActiveRecordQueryCache
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def enable_query_cache!
@query_cache_enabled[connection_cache_key(current_thread)] = true
connection.enable_query_cache! if active_connection?
end
def disable_query_cache!
@query_cache_enabled.delete connection_cache_key(current_thread)
connection.disable_query_cache! if active_connection?
end
def query_cache_enabled
@query_cache_enabled[connection_cache_key(current_thread)]
end
def active_connection?
@thread_cached_conns[connection_cache_key(current_thread)]
end
private
def current_thread
@lock_thread || Thread.current
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
end
end
end
...@@ -47,7 +47,7 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } ...@@ -47,7 +47,7 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
quality_level = Quality::TestLevel.new quality_level = Quality::TestLevel.new
RSpec.configure do |config| RSpec.configure do |config|
config.use_transactional_fixtures = false config.use_transactional_fixtures = true
config.use_instantiated_fixtures = false config.use_instantiated_fixtures = false
config.fixture_path = Rails.root config.fixture_path = Rails.root
...@@ -289,6 +289,16 @@ RSpec.configure do |config| ...@@ -289,6 +289,16 @@ RSpec.configure do |config|
config.before(:each, :https_pages_disabled) do |_| config.before(:each, :https_pages_disabled) do |_|
allow(Gitlab.config.pages).to receive(:external_https).and_return(false) allow(Gitlab.config.pages).to receive(:external_https).and_return(false)
end end
# We can't use an `around` hook here because the wrapping transaction
# is not yet opened at the time that is triggered
config.prepend_before do
Gitlab::Database.set_open_transactions_baseline
end
config.append_after do
Gitlab::Database.reset_open_transactions_baseline
end
end end
# add simpler way to match asset paths containing digest strings # add simpler way to match asset paths containing digest strings
......
...@@ -26,31 +26,22 @@ RSpec.configure do |config| ...@@ -26,31 +26,22 @@ RSpec.configure do |config|
end end
config.append_after(:context) do config.append_after(:context) do
DatabaseCleaner.clean_with(:deletion, cache_tables: false) delete_from_all_tables!
end end
config.before do config.around(:each, :delete) do |example|
setup_database_cleaner self.class.use_transactional_tests = false
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js) do example.run
DatabaseCleaner.strategy = :deletion, { except: deletion_except_tables, cache_tables: false }
end
config.before(:each, :delete) do delete_from_all_tables!(except: deletion_except_tables)
DatabaseCleaner.strategy = :deletion, { except: deletion_except_tables, cache_tables: false }
end end
config.before(:each, :migration) do config.around(:each, :migration) do |example|
DatabaseCleaner.strategy = :deletion, { cache_tables: false } self.class.use_transactional_tests = false
end
config.before do example.run
DatabaseCleaner.start
end
config.append_after do delete_from_all_tables!
DatabaseCleaner.clean
end end
end end
module DbCleaner module DbCleaner
def delete_from_all_tables!(except: nil)
DatabaseCleaner.clean_with(:deletion, cache_tables: false, except: except)
end
def deletion_except_tables def deletion_except_tables
[] []
end end
......
require 'gitlab/email/receiver'
shared_context :email_shared_context do shared_context :email_shared_context do
let(:mail_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" } let(:mail_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" }
let(:receiver) { Gitlab::Email::Receiver.new(email_raw) } let(:receiver) { Gitlab::Email::Receiver.new(email_raw) }
......
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