diff --git a/Makefile.PL b/Makefile.PL index d3d2da3..a0280e6 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -14,6 +14,7 @@ WriteMakefile( 'ExtUtils::MakeMaker' => '7.04', }, TEST_REQUIRES => { + 'Test2::Suite' => '0', # Test2::V0 'Test::More' => '0.96', # subtest does done_testing 'Test2::API' => '0', 'Capture::Tiny' => 0, @@ -21,7 +22,6 @@ WriteMakefile( 'Text::Diff' => '0', }, PREREQ_PM => { - 'Test::More' => '0.96', # subtest does done_testing 'Test2::API' => '0', 'Exporter' => '5.57', # exported "import" 'File::Path' => '2.07', # make_path diff --git a/lib/Test/Snapshot.pm b/lib/Test/Snapshot.pm index 18a9d7c..736aedc 100644 --- a/lib/Test/Snapshot.pm +++ b/lib/Test/Snapshot.pm @@ -2,8 +2,7 @@ package Test::Snapshot; use 5.008001; use strict; use warnings; -require Test::More; -use Test2::API qw(context); +use Test2::API qw(context test2_add_callback_pre_subtest); use Exporter 'import'; require Carp; require File::Spec; @@ -15,50 +14,75 @@ use Text::Diff; our $VERSION = "0.06"; our @EXPORT = qw(is_deeply_snapshot); +# capture subtest names +test2_add_callback_pre_subtest(sub { + my ($name, $code, @args) = @_; + 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->release; +}); + sub is_deeply_snapshot { my ($got, $description) = @_; + my $ctx = context(); + my $expected = "undef\n"; - my $filename = _get_filename($description); + my $filename = _get_filename($ctx, $description); + if (-f $filename) { no strict; local $@; $expected = eval { _read_file($filename) }; - Test::More::diag("Error in snapshot '$filename': $@") if $@; + $ctx->diag("Error in snapshot '$filename': $@") if $@; } else { - Test::More::diag("No snapshot filename '$filename' found"); + $ctx->diag("No snapshot filename '$filename' found"); } + my $dumper = Data::Dumper->new([$got]); $dumper->Indent(1)->Terse(1); $dumper->Sortkeys(1) if $dumper->can("Sortkeys"); my $dump = $dumper->Dump; + my $result = $dump eq $expected; - local $Test::Builder::Level = $Test::Builder::Level + 1; + if ($result) { - Test::More::pass($description); + $ctx->pass($description); } else { - Test::More::fail($description); - Test::More::diag(diff \$expected, \$dump); + $ctx->fail($description); + $ctx->diag(diff \$expected, \$dump); if ($ENV{TEST_SNAPSHOT_UPDATE}) { _make_dir_for($filename); _write_file($filename, $dump); } } - $result; + + $ctx->release; + return $result; } sub _get_filename { - my ($description) = @_; + my ($ctx, $description) = @_; Carp::croak("No description given") if !defined $description; - my $ctx = context(); - my ($topfile, @stack) = map $_->get_meta('Test::Builder')->{Name}, - $ctx->stack->all; - $ctx->release; - push @stack, $description if defined $description; - # turn the test-file location into its sibling called "snapshots/$basename" + + my @stack; + + for my $hub ($ctx->stack->all) { + my $names = $hub->get_meta('Test::Snapshot::subtest_names'); + push @stack, @$names if $names; + } + + my $topfile = $0; + my ($v, $d, $f) = File::Spec->splitpath(File::Spec->rel2abs($topfile)); unshift @stack, $f; + push @stack, $description; + @stack = map { my $t = $_; $t =~ s#[^a-z\-0-9]+#_#gi; $t } @stack; my $basename = pop @stack; + File::Spec->catpath( $v, File::Spec->catdir($d, 'snapshots', @stack), diff --git a/t/diff.t b/t/diff.t index 2277fe4..7ce716c 100644 --- a/t/diff.t +++ b/t/diff.t @@ -53,7 +53,7 @@ isnt $out, ''; $err =~ s#^.* at .* line \d+\.$##m; is $err, <<'EOF'; -# Failed test 'desc' +# Failed test 'desc' # @@ -1,3 +1,3 @@ # { diff --git a/t/snapshot-test2.t b/t/snapshot-test2.t new file mode 100644 index 0000000..e6adbe2 --- /dev/null +++ b/t/snapshot-test2.t @@ -0,0 +1,47 @@ +use Test2::V0; +use Test::Snapshot; +use File::Temp qw/ tempfile tempdir /; +use Capture::Tiny qw(capture); +use App::Prove; + +sub tempcopy { + my ($text, $dir) = @_; + my ($tfh, $filename) = tempfile( DIR => $dir ); + print $tfh $text; + close $tfh; + $filename; +} + +$ENV{TEST_SNAPSHOT_UPDATE} = 0; # override to ensure known value + +my $dir = tempdir( CLEANUP => 1 ); +my $filename = tempcopy(<<'EOF', $dir); +use Test2::V0; +use Test::Snapshot; + +subtest 'subtestname' => sub { + is_deeply_snapshot 'just some text', 'subtest desc'; +}; + +is_deeply_snapshot { message => 'output' }, 'desc'; + +done_testing; +EOF + +sub do_test { + my ($filename, $update, $expect, $description) = @_; + my ($out, $err, $exit) = capture { + local $ENV{TEST_SNAPSHOT_UPDATE} = $update; + my $app = App::Prove->new; + $app->process_args(qw(-b), $filename); + $app->run ? 0 : 1; + }; + is $exit, $expect, $description + or diag 'Output was: ', $out, 'Error was: ', $err; +} + +do_test($filename, '', 1, 'fails first time'); +do_test($filename, 1, 1, 'fails second time, snapshots were not created'); +do_test($filename, 1, 0, 'works third time, snapshots were created'); + +done_testing; diff --git a/t/snapshot.t b/t/snapshot-testmore.t similarity index 100% rename from t/snapshot.t rename to t/snapshot-testmore.t