lib-opal/opal/rspec/async/hooks.rb in opal-rspec-0.8.0 vs lib-opal/opal/rspec/async/hooks.rb in opal-rspec-1.0.0.alpha1
- old
+ new
@@ -1,12 +1,102 @@
-class RSpec::Core::Hooks::HookCollection
- def run
- # WAS:
- # hooks.each { |h| h.run(@example) }
- # NOW:
- hooks.inject(Promise.value(true)) do |previous_hook_promise, next_hook|
- previous_hook_promise.then do
- Promise.value(next_hook.run(@example))
+# await: *await*
+
+require 'rspec/core/hooks'
+
+module RSpec
+ module Core
+ module Hooks
+ class HookCollections
+ def run_example_hooks_for_await(example, position, each_method)
+ # WAS:
+ # owner_parent_groups.__send__(each_method) do |group|
+ # group.hooks.run_owned_hooks_for(position, :example, example)
+ # end
+ case each_method
+ when :each
+ groups = owner_parent_groups
+ when :reverse_each
+ groups = owner_parent_groups.reverse
+ else
+ raise "Unsupported each_method: #{each_method}"
+ end
+ groups.each_await do |group|
+ group.hooks.run_owned_hooks_for_await(position, :example, example)
+ end
+ end
+
+ def run_owned_hooks_for_await(position, scope, example_or_group)
+ # WAS:
+ # matching_hooks_for(position, scope, example_or_group).each do |hook|
+ # hook.run(example_or_group)
+ # end
+
+ matching_hooks_for(position, scope, example_or_group).each_await do |hook|
+ hook.run_await(example_or_group)
+ end
+ end
+
+ def run_await(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_await(position, :context, example_or_group)
+ end
+ else
+ case position
+ when :before then run_example_hooks_for_await(example_or_group, :before, :reverse_each)
+ when :after then run_example_hooks_for_await(example_or_group, :after, :each)
+ when :around then run_around_example_hooks_for_await(example_or_group) { yield.await }
+ end
+ end
+ end
+
+ def run_around_example_hooks_for_await(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.await }
+ hooks.inject(initial_procsy) do |procsy, around_hook|
+ procsy.wrap { around_hook.execute_with_await(example, procsy) }
+ end.call.await
+ end
+ end
+
+ class BeforeHook < Hook
+ def run_await(example)
+ example.instance_exec_await(example, &block)
+ end
+ end
+
+ # @private
+ class AfterHook < Hook
+ def run_await(example)
+ example.instance_exec_await(example, &block)
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
+ example.set_exception(ex)
+ end
+ end
+
+ # @private
+ class AfterContextHook < Hook
+ def run_await(example)
+ example.instance_exec_await(example, &block)
+ rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e
+ RSpec.configuration.reporter.notify_non_example_exception(e, "An error occurred in an `after(:context)` hook.")
+ end
+ end
+
+ class AroundHook < Hook
+ def execute_with_await(example, procsy)
+ example.instance_exec_await(procsy, &block)
+ return if procsy.executed?
+ Pending.mark_skipped!(example,
+ "#{hook_description} did not execute the example")
+ end
end
end
end
end