Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ 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,
'App::Prove' => 0,
'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
Expand Down
58 changes: 41 additions & 17 deletions lib/Test/Snapshot.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion t/diff.t
Original file line number Diff line number Diff line change
Expand Up @@ -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 @@
# {
Expand Down
47 changes: 47 additions & 0 deletions t/snapshot-test2.t
Original file line number Diff line number Diff line change
@@ -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;
File renamed without changes.