App-Project-Doctor
view release on metacpan or search on metacpan
t/function.t view on Meta::CPAN
check_name => 'Pod',
),
);
my $plain = $r->render_text(verbose => 0);
my $verbose = $r->render_text(verbose => 1);
unlike $plain, qr/Detailed explanation/, 'detail hidden in plain mode';
like $verbose, qr/Detailed explanation/, 'detail shown in verbose mode';
};
subtest 'Report::render_text -- fix list present only when fixable findings exist' => sub {
my $with_fix = _make_report(
_make_finding(
severity => $ERR_SEV,
message => 'Fixable problem',
check_name => 'CI',
fix => sub {},
),
);
like $with_fix->render_text,
qr/Suggested fixes:/,
'fix list appears when fixable findings present';
like $with_fix->render_text,
qr/Would you like me to apply them/,
'prompt appears';
my $no_fix = _make_report(
_make_finding(severity => $PASS_SEV, message => 'ok', check_name => 'CI'),
);
unlike $no_fix->render_text,
qr/Suggested fixes:/,
'no fix list when all findings are non-fixable';
};
subtest 'Report::render_text -- summary line formatting' => sub {
my $r_err = _make_report(_make_finding(severity => $ERR_SEV, message => 'e', check_name => 'A'));
my $r_warn = _make_report(_make_finding(severity => $WARN_SEV, message => 'w', check_name => 'A'));
my $r_both = _make_report(
_make_finding(severity => $ERR_SEV, message => 'e', check_name => 'A'),
_make_finding(severity => $WARN_SEV, message => 'w', check_name => 'B'),
);
my $r_none = _make_report(_make_finding(severity => $PASS_SEV, message => 'p', check_name => 'A'));
like $r_err->render_text, qr/1 error\(s\)/, 'error count';
like $r_warn->render_text, qr/1 warning\(s\)/, 'warning count';
like $r_both->render_text, qr/error.*warning/, 'both counts';
like $r_none->render_text, qr/No errors or warnings/, 'clean message';
};
subtest 'Report::render_json -- parseable and excludes fix' => sub {
my $r = _make_report(
_make_finding(
severity => $INFO_SEV,
message => 'note',
check_name => 'Meta',
fix => sub {},
),
);
my $json = $r->render_json;
returns_ok($json, { type => 'scalar' }, 'render_json returns a scalar');
require JSON::MaybeXS;
my $decoded = JSON::MaybeXS->new->decode($json);
is ref $decoded, 'ARRAY', 'decodes to arrayref';
ok !exists $decoded->[0]{fix}, 'fix not serialised';
is $decoded->[0]{check_name}, 'Meta', 'check_name present';
};
subtest 'Report::render_tap -- plan and ok/not-ok lines' => sub {
my $r = _make_report(
_make_finding(severity => $PASS_SEV, message => 'good', check_name => 'A'),
_make_finding(severity => $INFO_SEV, message => 'info', check_name => 'B'),
_make_finding(severity => $ERR_SEV, message => 'bad', check_name => 'C'),
_make_finding(severity => $WARN_SEV, message => 'warn', check_name => 'D'),
);
my $tap = $r->render_tap;
returns_ok($tap, { type => 'scalar' }, 'render_tap returns a scalar');
like $tap, qr/^1\.\.4/m, 'plan line';
like $tap, qr/^ok 1/m, 'pass is ok';
like $tap, qr/^ok 2/m, 'info is ok';
like $tap, qr/^not ok 3/m, 'error is not ok';
like $tap, qr/^not ok 4/m, 'warning is not ok';
};
subtest 'Report::_worst_severity -- rank order' => sub {
# Directly exercise the private helper since it is non-trivial logic.
my @err = (_make_finding(severity => $ERR_SEV, message => 'e', check_name => 'X'));
my @warn = (_make_finding(severity => $WARN_SEV, message => 'w', check_name => 'X'));
my @info = (_make_finding(severity => $INFO_SEV, message => 'i', check_name => 'X'));
my @pass = (_make_finding(severity => $PASS_SEV, message => 'p', check_name => 'X'));
my @mixed = (@err, @warn, @info, @pass);
is App::Project::Doctor::Report::_worst_severity(\@mixed), 'error', 'error dominates';
is App::Project::Doctor::Report::_worst_severity(\@warn), 'warning', 'warning when no error';
is App::Project::Doctor::Report::_worst_severity(\@info), 'info', 'info when only info';
is App::Project::Doctor::Report::_worst_severity(\@pass), 'pass', 'pass when only pass';
};
subtest 'Report -- memory cycle check' => sub {
my $r = _make_report(_make_finding(message => 'x', check_name => 'Y'));
memory_cycle_ok($r, 'Report has no circular references');
};
diag 'Report: done' if $ENV{TEST_VERBOSE};
# ===========================================================================
# 5. App::Project::Doctor::Fixer
# ===========================================================================
require_ok 'App::Project::Doctor::Fixer';
# Build a real Context so the type constraint in Fixer::new is satisfied.
my $FIXER_DIR = make_distro('Makefile.PL' => '');
my $FIXER_CTX = _make_ctx($FIXER_DIR);
subtest 'Fixer::new -- requires report and context' => sub {
my $r = _make_report;
my $f = App::Project::Doctor::Fixer->new(report => $r, context => $FIXER_CTX);
isa_ok $f, 'App::Project::Doctor::Fixer';
is $f->non_interactive, 0, 'non_interactive defaults to 0';
};
subtest 'Fixer::new -- type constraints enforced' => sub {
my $r = _make_report;
throws_ok {
App::Project::Doctor::Fixer->new(report => 'bad', context => $FIXER_CTX)
( run in 0.966 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )