1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
# frozen_string_literal: true
require "test_prof/core"
module TestProf
# `before_all` helper configuration
module BeforeAll
class AdapterMissing < StandardError # :nodoc:
MSG = "Please, provide an adapter for `before_all` " \
"through `TestProf::BeforeAll.adapter = MyAdapter`"
def initialize
super(MSG)
end
end
# Used in dry-run mode
class NoopAdapter
class << self
def begin_transaction(...)
end
def rollback_transaction(...)
end
def setup_fixtures(...)
end
end
end
class << self
attr_writer :adapter
def adapter
@adapter ||= default_adapter
end
def begin_transaction(scope = nil, metadata = [])
raise AdapterMissing if adapter.nil?
config.run_hooks(:begin, scope, metadata) do
adapter.begin_transaction
end
yield
end
def rollback_transaction(scope = nil, metadata = [])
raise AdapterMissing if adapter.nil?
config.run_hooks(:rollback, scope, metadata) do
adapter.rollback_transaction
end
end
def setup_fixtures(test_object)
raise ArgumentError, "Current adapter doesn't support #setup_fixtures" unless adapter.respond_to?(:setup_fixtures)
adapter.setup_fixtures(test_object)
end
def config
@config ||= Configuration.new
end
def configure
yield config
end
private
def default_adapter
return NoopAdapter if TestProf.dry_run?
if defined?(::ActiveRecord::Base)
require "test_prof/before_all/adapters/active_record"
Adapters::ActiveRecord
end
end
end
class HookEntry # :nodoc:
attr_reader :filters, :block
def initialize(block:, filters: [])
@block = block
@filters = TestProf.rspec? ? ::RSpec::Core::Metadata.build_hash_from(filters) : filters
end
def run(scope, metadata)
return unless filters_apply?(metadata)
block.call(scope)
end
private
def filters_apply?(metadata)
return true unless filters.is_a?(Hash) && TestProf.rspec?
::RSpec::Core::MetadataFilter.apply?(
:all?,
filters,
metadata
)
end
end
class HooksChain # :nodoc:
attr_reader :type, :after, :before
def initialize(type)
@type = type
@before = []
@after = []
end
def run(scope = nil, metadata = [])
before.each { |hook| hook.run(scope, metadata) }
yield
after.each { |hook| hook.run(scope, metadata) }
end
end
class Configuration
HOOKS = %i[begin rollback].freeze
attr_accessor :setup_fixtures
def initialize
@hooks = Hash.new { |h, k| h[k] = HooksChain.new(k) }
@setup_fixtures = false
end
# Add `before` hook for `begin` or
# `rollback` operation with optional filters:
#
# config.before(:rollback, foo: :bar) { ... }
def before(type, *filters, &block)
validate_hook_type!(type)
hooks[type].before << HookEntry.new(block: block, filters: filters) if block
end
# Add `after` hook for `begin` or
# `rollback` operation with optional filters:
#
# config.after(:begin, foo: :bar) { ... }
def after(type, *filters, &block)
validate_hook_type!(type)
hooks[type].after << HookEntry.new(block: block, filters: filters) if block
end
def run_hooks(type, scope = nil, metadata = []) # :nodoc:
validate_hook_type!(type)
hooks[type].run(scope, metadata) { yield }
end
private
def validate_hook_type!(type)
return if HOOKS.include?(type)
raise ArgumentError, "Unknown hook type: #{type}. Valid types: #{HOOKS.join(", ")}"
end
attr_reader :hooks
end
end
end
if defined?(::Isolator)
require "test_prof/before_all/isolator"
end
|