lib-opal/opal/rspec/async/example.rb in opal-rspec-0.8.0 vs lib-opal/opal/rspec/async/example.rb in opal-rspec-1.0.0.alpha1

- old
+ new

@@ -1,187 +1,99 @@ -require 'js' +# await: *await* -module ::RSpec::Core - class Example - # WAS: - # def run_after_example - # @example_group_class.hooks.run(:after, :example, self) - # verify_mocks - # assign_generated_description if RSpec.configuration.expecting_with_rspec? - # rescue Exception => e - # set_exception(e, "in an `after(:example)` hook") - # ensure - # @example_group_instance.teardown_mocks_for_rspec - # end - # NOW: - def run_after_example - @example_group_class.hooks.run(:after, :example, self).then do - verify_mocks - assign_generated_description if RSpec.configuration.expecting_with_rspec? - end.rescue do |e| - set_exception(e, "in an `after(:example)` hook") - end.ensure do - @example_group_instance.teardown_mocks_for_rspec - end - end +module RSpec + module Core + class Example + def run_await(example_group_instance, reporter) + # added awaits + @example_group_instance = example_group_instance + @reporter = reporter + RSpec.configuration.configure_example(self, hooks) + RSpec.current_example = self - def run(example_group_instance, reporter) - @example_group_instance = example_group_instance - RSpec.current_example = self + start(reporter) + Pending.mark_pending!(self, pending) if pending? - start(reporter) - Pending.mark_pending!(self, pending) if pending? - - # WAS: - # … - # begin - # if skipped? - # Pending.mark_pending! self, skip - # elsif !RSpec.configuration.dry_run? - # with_around_example_hooks do - # begin - # run_before_example - # @example_group_instance.instance_exec(self, &@example_block) - # - # if pending? - # Pending.mark_fixed! self - # - # raise Pending::PendingExampleFixedError, - # 'Expected example to fail since it is pending, but it passed.', - # [location] - # end - # rescue Pending::SkipDeclaredInExample - # # no-op, required metadata has already been set by the `skip` - # # method. - # rescue Exception => e - # set_exception(e) - # ensure - # run_after_example - # end - # end - # end - # rescue Exception => e - # set_exception(e) - # ensure - # @example_group_instance.instance_variables.each do |ivar| - # @example_group_instance.instance_variable_set(ivar, nil) - # end - # @example_group_instance = nil - # end - # - # finish(reporter) - # ensure - # RSpec.current_example = nil - Promise.value(true).then do - Promise.value(true).then do + begin if skipped? Pending.mark_pending! self, skip elsif !RSpec.configuration.dry_run? - with_around_example_hooks do - # WAS: - # with_around_example_hooks do - # begin - # run_before_example - # @example_group_instance.instance_exec(self, &@example_block) - # - # if pending? - # Pending.mark_fixed! self - # - # raise Pending::PendingExampleFixedError, - # 'Expected example to fail since it is pending, but it passed.', - # [location] - # end - # rescue Pending::SkipDeclaredInExample - # # no-op, required metadata has already been set by the `skip` - # # method. - # rescue Exception => e - # set_exception(e) - # ensure - # run_after_example - # end - # end - # NOW: - Promise.value(true).then do - run_before_example - .then do - # TODO: Use subject! to create a before hook on the fly, might be cleaner than this - # Might be a better way to do this, but then you end up with promises around the expectation handlers, which could get ugly - begin - subj = example_group_instance.subject - if subj.is_a? Promise - return subj.then do |resolved_subject| - # This is a private method, but we're using Opal - example_group_instance.__memoized[:subject] = resolved_subject - end - end - rescue StandardError, JS::Error - # Exception occurred while checking the subject, might be that the example - # group had a described class, was not intending on using it as the subject, - # and the initializer for that described class failed - end - Promise.value(true) - end - .then do - # WAS: - # @example_group_instance.instance_exec(self, &@example_block) - # NOW: - Promise.value(@example_group_instance.instance_exec(self, &@example_block)).then do |result| - result - end.rescue do |ex| - case ex - when nil then Exception.new 'Async promise failed for unspecified reason' - when Exception then ex - else Exception.new(ex) - end - end - end - .then do - # ORIGINAL: - if pending? - Pending.mark_fixed! self + with_around_and_singleton_context_hooks_await do + begin + run_before_example_await + RSpec.current_scope = :example + @example_group_instance.instance_exec_await(self, &@example_block) - raise Pending::PendingExampleFixedError, - 'Expected example to fail since it is pending, but it passed.', - [location] - end + if pending? + Pending.mark_fixed! self + + raise Pending::PendingExampleFixedError, + 'Expected example to fail since it is pending, but it passed.', + [location] end - end.rescue do |e| - # WAS: - # rescue Pending::SkipDeclaredInExample - # # no-op, required metadata has already been set by the `skip` - # # method. - # rescue Exception => e - # set_exception(e) - # ensure - # run_after_example - # end - # NOW: - case e - when Pending::SkipDeclaredInExample - # no-op, required metadata has already been set by the `skip` - # method. - when Exception - set_exception(e) - end - end.ensure do - run_after_example + rescue Pending::SkipDeclaredInExample => _ + # The "=> _" is normally useless but on JRuby it is a workaround + # for a bug that prevents us from getting backtraces: + # https://github.com/jruby/jruby/issues/4467 + # + # no-op, required metadata has already been set by the `skip` + # method. + rescue AllExceptionsExcludingDangerousOnesOnRubiesThatAllowIt => e + set_exception(e) + ensure + RSpec.current_scope = :after_example_hook + run_after_example_await end end end - end.rescue do |e| + rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e set_exception(e) - end.ensure do - @example_group_instance.instance_variables.each do |ivar| - @example_group_instance.instance_variable_set(ivar, nil) - end - @example_group_instance = nil + ensure + @example_group_instance = nil # if you love something... let it go end - end.then do + finish(reporter) - end.ensure do |result| + ensure + execution_result.ensure_timing_set(clock) RSpec.current_example = nil - # promise always/ensure do not behave exactly like ensure, need to be explicit about value being returned - result + end + + def run_before_example_await + # added awaits + @example_group_instance.setup_mocks_for_rspec + hooks.run_await(:before, :example, self) + end + + def run_after_example_await + # added awaits + assign_generated_description if defined?(::RSpec::Matchers) + hooks.run_await(:after, :example, self) + verify_mocks + ensure + @example_group_instance.teardown_mocks_for_rspec + end + + def with_around_and_singleton_context_hooks_await + singleton_context_hooks_host = example_group_instance.singleton_class + singleton_context_hooks_host.run_before_context_hooks_await(example_group_instance) + with_around_example_hooks_await { yield.await } + ensure + singleton_context_hooks_host.run_after_context_hooks_await(example_group_instance) + end + + def with_around_example_hooks_await + RSpec.current_scope = :before_example_hook + hooks.run_await(:around, :example, self) { yield.await } + rescue Support::AllExceptionsExceptOnesWeMustNotRescue => e + set_exception(e) + end + + def instance_exec_await(*args, &block) + @example_group_instance.instance_exec_await(*args, &block) + end + + class Procsy + alias run_await run end end end end