diff --git a/src/spectator/dsl/hooks.cr b/src/spectator/dsl/hooks.cr index bc110d4..85dd6be 100644 --- a/src/spectator/dsl/hooks.cr +++ b/src/spectator/dsl/hooks.cr @@ -29,7 +29,7 @@ module Spectator {{block.body}} end - # TODO: Handle wrapping proc and test together. + ::Spectator::SpecBuilder.add_around_each_hook { |test, proc| test.as({{@type.id}}).%hook(proc) } end end end diff --git a/src/spectator/example_hooks.cr b/src/spectator/example_hooks.cr index 28d8a24..dd335da 100644 --- a/src/spectator/example_hooks.cr +++ b/src/spectator/example_hooks.cr @@ -10,7 +10,7 @@ module Spectator [] of TestMethod, [] of ->, [] of TestMethod, - [] of Proc(Nil) -> + [] of ::SpectatorTest, Proc(Nil) -> ) end @@ -20,7 +20,7 @@ module Spectator @before_each : Array(TestMethod), @after_all : Array(->), @after_each : Array(TestMethod), - @around_each : Array(Proc(Nil) ->) + @around_each : Array(::SpectatorTest, Proc(Nil) ->) ) end @@ -56,19 +56,18 @@ module Spectator # in addition to a block passed to this method. # To call the block and all "around-each" hooks, # just invoke `Proc#call` on the returned proc. - def wrap_around_each(&block : ->) : -> + def wrap_around_each(test, block : ->) wrapper = block # Must wrap in reverse order, # otherwise hooks will run in the wrong order. @around_each.reverse_each do |hook| - wrapper = wrap_proc(hook, wrapper) + wrapper = wrap_foo(test, hook, wrapper) end wrapper end - # Utility method for wrapping one proc with another. - private def wrap_proc(inner : Proc(Nil) ->, wrapper : ->) - ->{ inner.call(wrapper) } + private def wrap_foo(test, hook, wrapper) + ->{ hook.call(test, wrapper) } end end end diff --git a/src/spectator/runnable_example.cr b/src/spectator/runnable_example.cr index 2ee66f0..630c2ac 100644 --- a/src/spectator/runnable_example.cr +++ b/src/spectator/runnable_example.cr @@ -25,11 +25,13 @@ module Spectator # Runs the test code and captures the result. private def run_example(result) + wrapper = test_wrapper.around_hook(group.context) + # Capture how long it takes to run the test code. result.elapsed = Time.measure do begin - test_wrapper.run # Actually run the example code. - rescue ex # Catch all errors and handle them later. + wrapper.call + rescue ex # Catch all errors and handle them later. result.error = ex end end diff --git a/src/spectator/spec_builder.cr b/src/spectator/spec_builder.cr index 25404a0..880105b 100644 --- a/src/spectator/spec_builder.cr +++ b/src/spectator/spec_builder.cr @@ -70,9 +70,9 @@ module Spectator end # Adds a block of code to run before and after each example in the current group. - # The block of code will be given another proc as an argument. - # It is expected that the block will call the proc. - def add_around_each_hook(&block : Proc(Nil) ->) : Nil + # The block of code will be given another hook as an argument. + # It is expected that the block will call the hook. + def add_around_each_hook(&block : ::SpectatorTest, Proc(Nil) ->) : Nil @@stack.current.add_around_each_hook(block) end diff --git a/src/spectator/spec_builder/example_group_builder.cr b/src/spectator/spec_builder/example_group_builder.cr index d02c33c..f7d6255 100644 --- a/src/spectator/spec_builder/example_group_builder.cr +++ b/src/spectator/spec_builder/example_group_builder.cr @@ -11,6 +11,7 @@ module Spectator::SpecBuilder @after_each_hooks = Deque(TestMethod).new @before_all_hooks = Deque(->).new @after_all_hooks = Deque(->).new + @around_each_hooks = Deque(::SpectatorTest, Proc(Nil) ->).new def add_child(child : Child) @children << child @@ -32,13 +33,17 @@ module Spectator::SpecBuilder @after_all_hooks << hook end + def add_around_each_hook(hook : ::SpectatorTest, Proc(Nil) ->) + @around_each_hooks << hook + end + private def build_hooks ExampleHooks.new( @before_all_hooks.to_a, @before_each_hooks.to_a, @after_all_hooks.to_a, @after_each_hooks.to_a, - [] of Proc(Nil) -> + @around_each_hooks.to_a ) end end diff --git a/src/spectator/test_context.cr b/src/spectator/test_context.cr index fea0ab4..d02f906 100644 --- a/src/spectator/test_context.cr +++ b/src/spectator/test_context.cr @@ -42,5 +42,14 @@ module Spectator @hooks.run_after_each(wrapper) @parent.try &.run_after_each_hooks(wrapper) end + + def wrap_around_each_hooks(test, &block : ->) + wrapper = @hooks.wrap_around_each(test, block) + if (parent = @parent) + parent.wrap_around_each_hooks(test, &wrapper) + else + wrapper + end + end end end diff --git a/src/spectator/test_wrapper.cr b/src/spectator/test_wrapper.cr index b087623..99c1512 100644 --- a/src/spectator/test_wrapper.cr +++ b/src/spectator/test_wrapper.cr @@ -24,5 +24,9 @@ module Spectator def call(method : TestMethod) : Nil method.call(@test) end + + def around_hook(context : TestContext) + context.wrap_around_each_hooks(@test) { run } + end end end