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 )