App-Project-Doctor
view release on metacpan or search on metacpan
t/integration.t view on Meta::CPAN
my $text = $report->render_text;
like( $text, qr/\[v\]/, 'pass icon [v] present' );
like( $text, qr/\[X\]/, 'error icon [X] present' );
like( $text, qr/\[i\]/, 'info icon [i] present' );
like( $text, qr/Tests/, 'check_name Tests appears in output' );
like( $text, qr/Security/, 'check_name Security appears in output' );
like( $text, qr/1 error/, 'error count in summary line' );
unlike( $text, qr/No errors or warnings/, 'no-error message absent when errors present' );
diag $text if $ENV{TEST_VERBOSE};
};
subtest 'render_text verbose mode shows detail; non-verbose hides it' => sub {
my $detail_text = 'Extended diagnostic detail here';
my $report = $Report->new;
$report->add_findings(_f(
severity => 'error',
message => 'Primary message',
detail => $detail_text,
check_name => 'TestCheck',
));
my $plain = $report->render_text(verbose => 0);
my $verbose = $report->render_text(verbose => 1);
unlike( $plain, qr/\Q$detail_text\E/, 'detail hidden when verbose => 0' );
like( $verbose, qr/\Q$detail_text\E/, 'detail shown when verbose => 1' );
};
subtest 'render_tap produces a valid TAP stream' => sub {
my $report = $Report->new;
$report->add_findings(
_f(severity => 'pass', message => 'Tests ok', check_name => 'Tests'),
_f(severity => 'error', message => 'POD error', check_name => 'POD'),
);
my $tap = $report->render_tap;
like( $tap, qr/^1\.\.2$/m, 'TAP plan line 1..2' );
like( $tap, qr/^ok 1\b/m, 'first finding is ok' );
like( $tap, qr/^not ok 2\b/m, 'second (error) finding is not ok' );
like( $tap, qr/\[Tests\]/, 'check_name included in TAP line' );
diag $tap if $ENV{TEST_VERBOSE};
};
subtest 'render_json returns parseable array with expected keys; fix excluded' => sub {
my $report = $Report->new;
$report->add_findings(_f(
severity => 'error',
message => 'A JSON finding',
detail => 'some detail',
check_name => 'TestCheck',
file => 'lib/T.pm',
line => 42,
fix => sub { 1 },
));
require JSON::MaybeXS;
my $json_str = $report->render_json;
my $decoded = JSON::MaybeXS->new->decode($json_str);
ok( ref $decoded eq 'ARRAY', 'decoded JSON is an array' );
is( scalar @{$decoded}, 1, 'one element in array' );
is( $decoded->[0]{severity}, 'error', 'severity key correct' );
is( $decoded->[0]{message}, 'A JSON finding', 'message key correct' );
is( $decoded->[0]{check_name}, 'TestCheck', 'check_name key correct' );
is( $decoded->[0]{file}, 'lib/T.pm', 'file key correct' );
is( $decoded->[0]{line}, 42, 'line key correct' );
ok( !exists $decoded->[0]{fix}, 'fix coderef excluded from JSON output' );
diag $json_str if $ENV{TEST_VERBOSE};
};
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
# 3. OPTIONAL DEPENDENCY: JSON::MaybeXS
# Strategy: mock_scoped replaces JSON::MaybeXS::new with a sub that throws,
# simulating the module being unavailable. This is more portable than
# Test::Without::Module + INC manipulation, which behaves differently across
# Perl versions (runtime eval of 'use' does not reliably install the @INC hook).
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
subtest 'render_json throws when JSON::MaybeXS backend fails' => sub {
require JSON::MaybeXS;
my $report = $Report->new;
$report->add_findings(_f(severity => 'info', message => 'x', check_name => 'T'));
# Replace new() for the duration of this block; the guard restores it on exit.
my $g = mock_scoped 'JSON::MaybeXS::new'
=> sub { die "Simulated: JSON::MaybeXS unavailable\n" };
throws_ok { $report->render_json }
qr/JSON::MaybeXS unavailable/,
'render_json propagates exception when JSON::MaybeXS backend fails';
};
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
# 4. FIXER NON-INTERACTIVE
# Strategy: Verify that the Report->Fixer->apply_all workflow fires each fix
# coderef exactly once (in insertion order) and returns the correct count.
# A non-fixable finding is included to confirm it is not counted.
# âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
subtest 'fixer non_interactive applies all fixable findings and returns correct count' => sub {
my $dir = tempdir(CLEANUP => 1);
my $ctx = $Context->new(root => $dir);
my @applied;
my $report = _report_with_fixable(\@applied, 3);
# Add a non-fixable finding to confirm it does not inflate the count.
$report->add_findings(_f(severity => 'info', message => 'No fix', check_name => 'T'));
my $fixer = $Fixer->new(report => $report, context => $ctx, non_interactive => 1);
my ($count, $out);
{
open(local *STDOUT, '>', \$out) or die;
$count = $fixer->run;
}
is( $count, 3, 'three fixable findings applied' );
is_deeply( \@applied, [qw(fix1 fix2 fix3)], 'fix coderefs called in insertion order' );
diag "Fixer output:\n$out" if $ENV{TEST_VERBOSE};
};
subtest 'fixer returns 0 immediately when report has no fixable findings' => sub {
my $dir = tempdir(CLEANUP => 1);
my $ctx = $Context->new(root => $dir);
my $report = $Report->new;
( run in 1.613 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )