class RSpec::Core::Hooks::HookCollections
Experimental RBS support (using type sampling data from the type_fusion
project).
# sig/rspec/core/hooks.rbs class RSpec::Core::Hooks::HookCollections def all_hooks_for: (Symbol position, Symbol scope) -> untyped def hooks_for: (Symbol position, Symbol scope) -> nil def matching_hooks_for: (Symbol position, Symbol scope, RSpec::Core::Example example_or_group) -> untyped def owner_parent_groups: () -> untyped def owner_parent_groups: () -> untyped def process: ((Class | RSpec::Core::Example) host, Array[Class] parent_groups, RSpec::Core::Hooks::HookCollections globals, Symbol position, Symbol scope) -> nil def processable_hooks_for: (Symbol position, Symbol scope, (Class | RSpec::Core::Example) host) -> untyped def run_example_hooks_for: (RSpec::Core::Example example, Symbol position, Symbol each_method) -> untyped def run_owned_hooks_for: (Symbol position, Symbol scope, RSpec::Core::Example example_or_group) -> untyped end
asking this class for a list of hooks, and then doing something with them.
API, so that callers tell this class what to do with the hooks, rather than
This is only possible because this interface provides a “tell, don’t ask”-style
case of a group having no hooks.
a hook is added. This allows us to avoid many object allocations for the common
this, so that, for example, hook collection objects are only instantiated when
implementation details behind this facade, it’s allowed us to heavily optimize
This provides the primary API used by other parts of rspec-core. By hiding all
@private
def all_hooks_for(position, scope)
Experimental RBS support (using type sampling data from the type_fusion
project).
def all_hooks_for: (Symbol position, Symbol scope) -> untyped
This signature was generated using 1 sample from 1 application.
def all_hooks_for(position, scope) hooks_for(position, scope) { return EMPTY_HOOK_ARRAY }.items_and_filters.map(&:first) end
def ensure_hooks_initialized_for(position, scope)
def ensure_hooks_initialized_for(position, scope) if position == :before if scope == :example @before_example_hooks ||= @filterable_item_repo_class.new(:all?) else @before_context_hooks ||= @filterable_item_repo_class.new(:all?) end elsif position == :after if scope == :example @after_example_hooks ||= @filterable_item_repo_class.new(:all?) else @after_context_hooks ||= @filterable_item_repo_class.new(:all?) end else # around @around_example_hooks ||= @filterable_item_repo_class.new(:all?) end end
def extract_scope_from(args)
def extract_scope_from(args) if known_scope?(args.first) normalized_scope_for(args.shift) elsif args.any? { |a| a.is_a?(Symbol) } error_message = "You must explicitly give a scope " \ "(#{SCOPES.join(", ")}) or scope alias " \ "(#{SCOPE_ALIASES.keys.join(", ")}) when using symbols as " \ "metadata for a hook." raise ArgumentError.new error_message else :example end end
def hooks_for(position, scope)
Experimental RBS support (using type sampling data from the type_fusion
project).
def hooks_for: (Symbol position, Symbol scope) -> nil
This signature was generated using 5 samples from 1 application.
def hooks_for(position, scope) if position == :before scope == :example ? @before_example_hooks : @before_context_hooks elsif position == :after scope == :example ? @after_example_hooks : @after_context_hooks else # around @around_example_hooks end || yield end
def initialize(owner, filterable_item_repo_class)
def initialize(owner, filterable_item_repo_class) @owner = owner @filterable_item_repo_class = filterable_item_repo_class @before_example_hooks = nil @after_example_hooks = nil @before_context_hooks = nil @after_context_hooks = nil @around_example_hooks = nil end
def known_scope?(scope)
def known_scope?(scope) SCOPES.include?(scope) || SCOPE_ALIASES.keys.include?(scope) end
def matching_hooks_for(position, scope, example_or_group)
Experimental RBS support (using type sampling data from the type_fusion
project).
def matching_hooks_for: (Symbol position, Symbol scope, RSpec::Core::Example example_or_group) -> untyped
This signature was generated using 3 samples from 1 application.
def matching_hooks_for(position, scope, example_or_group) repository = hooks_for(position, scope) { return EMPTY_HOOK_ARRAY } # It would be nice to not have to switch on type here, but # we don't want to define `ExampleGroup#metadata` because then # `metadata` from within an individual example would return the # group's metadata but the user would probably expect it to be # the example's metadata. metadata = case example_or_group when ExampleGroup then example_or_group.class.metadata else example_or_group.metadata end repository.items_for(metadata) end
def normalized_scope_for(scope)
def normalized_scope_for(scope) SCOPE_ALIASES[scope] || scope end
def owner_parent_groups
Experimental RBS support (using type sampling data from the type_fusion
project).
def owner_parent_groups: () -> untyped
This signature was generated using 1 sample from 1 application.
def owner_parent_groups @owner.parent_groups end
def owner_parent_groups
Experimental RBS support (using type sampling data from the type_fusion
project).
def owner_parent_groups: () -> untyped
This signature was generated using 1 sample from 1 application.
Ruby < 2.1 (see https://bugs.ruby-lang.org/issues/8035)
def owner_parent_groups @owner_parent_groups ||= [@owner] + @owner.parent_groups end
def process(host, parent_groups, globals, position, scope)
Experimental RBS support (using type sampling data from the type_fusion
project).
def process: ((Class | RSpec::Core::Example) host, Class | Class parent_groups, RSpec::Core::Hooks::HookCollections globals, Symbol position, Symbol scope) -> nil
This signature was generated using 4 samples from 1 application.
def process(host, parent_groups, globals, position, scope) hooks_to_process = globals.processable_hooks_for(position, scope, host) return if hooks_to_process.empty? hooks_to_process -= FlatMap.flat_map(parent_groups) do |group| group.hooks.all_hooks_for(position, scope) end return if hooks_to_process.empty? repository = ensure_hooks_initialized_for(position, scope) hooks_to_process.each { |hook| repository.append hook, (yield hook) } end
def processable_hooks_for(position, scope, host)
Experimental RBS support (using type sampling data from the type_fusion
project).
def processable_hooks_for: (Symbol position, Symbol scope, (Class | RSpec::Core::Example) host) -> untyped
This signature was generated using 3 samples from 1 application.
def processable_hooks_for(position, scope, host) if scope == :example all_hooks_for(position, scope) else matching_hooks_for(position, scope, host) end end
def register(prepend_or_append, position, *args, &block)
def register(prepend_or_append, position, *args, &block) scope, options = scope_and_options_from(*args) if scope == :suite # TODO: consider making this an error in RSpec 4. For SemVer reasons, # we are only warning in RSpec 3. RSpec.warn_with "WARNING: `#{position}(:suite)` hooks are only supported on " \ "the RSpec configuration object. This " \ "`#{position}(:suite)` hook, registered on an example " \ "group, will be ignored." return elsif scope == :context && position == :around # TODO: consider making this an error in RSpec 4. For SemVer reasons, # we are only warning in RSpec 3. RSpec.warn_with "WARNING: `around(:context)` hooks are not supported and " \ "behave like `around(:example)." end hook = HOOK_TYPES[position][scope].new(block, options) ensure_hooks_initialized_for(position, scope).__send__(prepend_or_append, hook, options) end
def register_global_singleton_context_hooks(example, globals)
def register_global_singleton_context_hooks(example, globals) parent_groups = example.example_group.parent_groups process(example, parent_groups, globals, :before, :context) { {} } process(example, parent_groups, globals, :after, :context) { {} } end
def register_globals(host, globals)
def register_globals(host, globals) parent_groups = host.parent_groups process(host, parent_groups, globals, :before, :example, &:options) process(host, parent_groups, globals, :after, :example, &:options) process(host, parent_groups, globals, :around, :example, &:options) process(host, parent_groups, globals, :before, :context, &:options) process(host, parent_groups, globals, :after, :context, &:options) end
def run(position, scope, example_or_group)
- Private: -
def run(position, scope, example_or_group) return if RSpec.configuration.dry_run? if scope == :context unless example_or_group.class.metadata[:skip] run_owned_hooks_for(position, :context, example_or_group) end else case position when :before then run_example_hooks_for(example_or_group, :before, :reverse_each) when :after then run_example_hooks_for(example_or_group, :after, :each) when :around then run_around_example_hooks_for(example_or_group) { yield } end end end
def run_around_example_hooks_for(example)
def run_around_example_hooks_for(example) hooks = FlatMap.flat_map(owner_parent_groups) do |group| group.hooks.matching_hooks_for(:around, :example, example) end return yield if hooks.empty? # exit early to avoid the extra allocation cost of `Example::Procsy` initial_procsy = Example::Procsy.new(example) { yield } hooks.inject(initial_procsy) do |procsy, around_hook| procsy.wrap { around_hook.execute_with(example, procsy) } end.call end
def run_example_hooks_for(example, position, each_method)
Experimental RBS support (using type sampling data from the type_fusion
project).
def run_example_hooks_for: (RSpec::Core::Example example, Symbol position, Symbol each_method) -> untyped
This signature was generated using 1 sample from 1 application.
def run_example_hooks_for(example, position, each_method) owner_parent_groups.__send__(each_method) do |group| group.hooks.run_owned_hooks_for(position, :example, example) end end
def run_owned_hooks_for(position, scope, example_or_group)
Experimental RBS support (using type sampling data from the type_fusion
project).
def run_owned_hooks_for: (Symbol position, Symbol scope, RSpec::Core::Example example_or_group) -> untyped
This signature was generated using 2 samples from 1 application.
def run_owned_hooks_for(position, scope, example_or_group) matching_hooks_for(position, scope, example_or_group).each do |hook| hook.run(example_or_group) end end
def scope_and_options_from(*args)
def scope_and_options_from(*args) return :suite if args.first == :suite scope = extract_scope_from(args) meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering) return scope, meta end