module Supercov
module RSpecAdapter
RUNNER = "rspec"
module ExampleHooks
def with_around_and_singleton_context_hooks(*args, &block)
Supercov::RSpecAdapter.enter(self, "setup")
super
end
def run_before_example
result = super
Supercov::RSpecAdapter.enter(self, "call")
result
end
def run_after_example
Supercov::RSpecAdapter.enter(self, "teardown")
super
end
def set_exception(exception)
Supercov::RSpecAdapter.note_exception(self)
Supercov::RSpecAdapter.without_own_frames(exception)
super
end
def finish(reporter)
result = super
Supercov::RSpecAdapter.finish(self)
result
end
end
@runtime = nil
@state = {}
def self.install(runtime)
return if @runtime
@runtime = runtime
runtime.adapter_active = true
::RSpec::Core::Example.prepend(ExampleHooks)
end
def self.without_own_frames(exception)
@runtime.without_own_frames(exception)
return unless exception.respond_to?(:all_exceptions)
exception.all_exceptions.each { |failure| @runtime.without_own_frames(failure) }
rescue StandardError
nil
end
def self.identity(example)
id = example.id.to_s.sub(%r{\A\./}, "")
retry_index = example.metadata[:retry_attempts].to_i
{ worker: @runtime.worker, test: id, retry: retry_index, phase: nil }
end
RUN_KEYS = %i[skip pending focus aggregate_failures].freeze
def self.tags(example)
metadata = example.metadata
tags = []
metadata.each do |key, value|
tags << key.to_s if value == true && key.is_a?(Symbol) && !RUN_KEYS.include?(key)
end
type = metadata[:type]
tags << type.to_s if type.is_a?(Symbol) || type.is_a?(String)
tags.uniq
rescue StandardError
[]
end
def self.source_file(example)
metadata = example.metadata
metadata[:absolute_file_path] || metadata[:file_path]
end
def self.enter(example, phase)
state = (@state[example.object_id] ||= { failed: {} })
state[:phase] = phase
identity = identity(example)
identity[:phase] = phase
@runtime.switch(identity)
end
def self.note_exception(example)
state = @state[example.object_id]
return unless state
state[:failed][state[:phase]] = true if state[:phase]
end
def self.finish(example)
state = @state.delete(example.object_id)
return unless state
identity = identity(example)
status = example.execution_result.status
call_outcome =
case status
when :passed then "passed"
when :pending then "skipped"
else "failed"
end
xfail = example.execution_result.pending_fixed? || (status == :pending && !example.execution_result.exception.nil?)
tags = tags(example)
title = example.full_description rescue nil
%w[setup call teardown].each do |phase|
outcome = if state[:failed][phase]
"failed"
elsif phase == "call"
call_outcome
else
"passed"
end
@runtime.outcome(identity[:worker], identity[:test], identity[:retry], phase, outcome, xfail, RUNNER, source_file(example), tags, title)
end
@runtime.switch(nil)
end
end
end