diff --git a/MANIFEST b/MANIFEST index 5a2e98a..ab6d75c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,4 +9,6 @@ t/errors.t t/snapshot-test2.t t/snapshot-testmore.t t/snapshots/errors_t/error +t/subtest-names-test2.t +t/subtest-names-testmore.t t/undef.t diff --git a/lib/Test/Snapshot.pm b/lib/Test/Snapshot.pm index 0f3d8ac..d75d1fa 100644 --- a/lib/Test/Snapshot.pm +++ b/lib/Test/Snapshot.pm @@ -14,14 +14,12 @@ use Text::Diff; our $VERSION = "0.061"; our @EXPORT = qw(is_deeply_snapshot); -# capture subtest names +# capture subtest names: called before the child hub is created, so the +# current hub is the parent; it records the name of its running child test2_add_callback_pre_subtest(sub { - my ($name, $code, @args) = @_; + my ($name) = @_; my $ctx = context(); - my $hub = $ctx->hub; - my @existing = @{$hub->get_meta('Test::Snapshot::subtest_names') // []}; - push @existing, $name; - $hub->set_meta('Test::Snapshot::subtest_names', \@existing); + $ctx->hub->set_meta('Test::Snapshot::subtest_name', $name); $ctx->release; }); @@ -60,8 +58,18 @@ sub is_deeply_snapshot { sub _get_filename { my ($ctx, $description) = @_; Carp::croak("No description given") if !defined $description; - my @stack = map $_->get_meta('Test::Snapshot::subtest_names'), $ctx->stack->all; - @stack = map @$_, grep $_, @stack; + # a subtest hub's name is the one Test::Builder stored on it, else the + # one recorded on the hub below it by the pre_subtest callback + my @hubs = $ctx->stack->all; + my @stack; + for my $i (1 .. $#hubs) { + next unless $hubs[$i]->isa('Test2::Hub::Subtest'); + my $tb_meta = $hubs[$i]->get_meta('Test::Builder'); + my $name = $tb_meta ? $tb_meta->{Name} : undef; + $name = $hubs[$i - 1]->get_meta('Test::Snapshot::subtest_name') + if !defined $name; + push @stack, $name if defined $name; + } my $topfile = $0; my ($v, $d, $f) = File::Spec->splitpath(File::Spec->rel2abs($topfile)); unshift @stack, $f; diff --git a/t/subtest-names-test2.t b/t/subtest-names-test2.t new file mode 100644 index 0000000..5446f1e --- /dev/null +++ b/t/subtest-names-test2.t @@ -0,0 +1,45 @@ +use Test2::V0; +use Test::Snapshot; +use Test2::API qw(context intercept); +use File::Spec; +use File::Basename qw(dirname); + +# snapshot path below snapshots// +sub rel_path { + my $ctx = context(); + my $filename = Test::Snapshot::_get_filename($ctx, 'desc'); + $ctx->release; + my $dir = File::Spec->catdir(dirname(File::Spec->rel2abs($0)), 'snapshots'); + my (undef, @parts) = File::Spec->splitdir(File::Spec->abs2rel($filename, $dir)); + join '/', @parts; +} + +sub path_is { + my ($expected) = @_; + my $ctx = context(); + is rel_path(), $expected, "path in $expected"; + $ctx->release; +} + +for my $top (qw(t1 t2)) { + subtest $top => sub { + path_is("$top/desc"); + for my $name (qw(a b)) { + subtest $name => sub { + path_is("$top/$name/desc"); + subtest inner => sub { path_is("$top/$name/inner/desc") }; + }; + } + path_is("$top/desc"); + }; +} +path_is('desc'); + +subtest intercept => sub { + subtest sibling => sub { pass }; + my $got; + intercept { $got = rel_path() }; + is $got, 'intercept/desc', 'intercept hub adds no name'; +}; + +done_testing; diff --git a/t/subtest-names-testmore.t b/t/subtest-names-testmore.t new file mode 100644 index 0000000..c9624a0 --- /dev/null +++ b/t/subtest-names-testmore.t @@ -0,0 +1,52 @@ +use Test::More 0.96; +use Test::Snapshot; +use Test2::API qw(context intercept); +use File::Spec; +use File::Basename qw(dirname); + +# snapshot path below snapshots// +sub rel_path { + my $ctx = context(); + my $filename = Test::Snapshot::_get_filename($ctx, 'desc'); + $ctx->release; + my $dir = File::Spec->catdir(dirname(File::Spec->rel2abs($0)), 'snapshots'); + my (undef, @parts) = File::Spec->splitdir(File::Spec->abs2rel($filename, $dir)); + join '/', @parts; +} + +sub path_is { + my ($expected) = @_; + my $ctx = context(); + is rel_path(), $expected, "path in $expected"; + $ctx->release; +} + +for my $top (qw(t1 t2)) { + subtest $top => sub { + path_is("$top/desc"); + for my $name (qw(a b)) { + subtest $name => sub { + path_is("$top/$name/desc"); + subtest inner => sub { path_is("$top/$name/inner/desc") }; + }; + } + path_is("$top/desc"); + }; +} +path_is('desc'); + +subtest intercept => sub { + subtest sibling => sub { pass }; + my $got; + intercept { $got = rel_path() }; + is $got, 'intercept/desc', 'intercept hub adds no name'; +}; + +subtest child => sub { + subtest sibling => sub { pass }; + my $child = Test::Builder->new->child('kid'); + path_is('child/kid/desc'); + $child->finalize; +}; + +done_testing;