App-Project-Doctor

 view release on metacpan or  search on metacpan

t/function.t  view on Meta::CPAN

# t/function.t -- White-box function tests for every .pm in lib/
#
# Tests are organized one subtest-block per module, in dependency order
# (value objects first, orchestrators last).
#
# Mocking: Test::Mockingbird -- mock/mock_scoped/mock_return/mock_exception/
# mock_once/mock_sequence/spy/restore_all.
# Return validation: Test::Returns -- returns_ok / returns_not_ok.

use strict;
use warnings;

use Test::Most;
use Test::Mockingbird;
use Test::Returns;
use Test::Memory::Cycle;
use File::Temp  qw(tempdir);
use File::Spec;
use File::Path  qw(make_path);
use Scalar::Util qw(blessed);
use Readonly;

Readonly::Scalar my $EMPTY    => '';
Readonly::Scalar my $NL       => "\n";
Readonly::Scalar my $PASS_SEV => 'pass';
Readonly::Scalar my $ERR_SEV  => 'error';
Readonly::Scalar my $WARN_SEV => 'warning';
Readonly::Scalar my $INFO_SEV => 'info';

# ---------------------------------------------------------------------------
# Shared helpers
# ---------------------------------------------------------------------------

# Build a temporary directory tree from a flat hash of rel-path => content.
sub make_distro {
	my (%files) = @_;
	my $dir = tempdir(CLEANUP => 1);
	for my $rel (sort keys %files) {
		my @parts  = split m{/}, $rel;
		my $abs    = File::Spec->catfile($dir, @parts);
		(my $parent = $abs) =~ s{[/\\][^/\\]+$}{};
		make_path($parent) unless -d $parent;
		open my $fh, '>', $abs or die "Cannot write $abs: $!";
		print {$fh} $files{$rel};
		close $fh;
	}
	return $dir;
}

# Construct a minimal Finding for use in other module tests.
sub _make_finding {
	require App::Project::Doctor::Finding;
	return App::Project::Doctor::Finding->new(@_);
}

# Construct a minimal Context for a given tempdir root.
sub _make_ctx {
	my $root = shift;
	require App::Project::Doctor::Context;
	return App::Project::Doctor::Context->new(root => $root);
}

# Construct a Report with an optional list of pre-loaded findings.
sub _make_report {
	require App::Project::Doctor::Report;
	my $r = App::Project::Doctor::Report->new;
	$r->add_findings(@_) if @_;
	return $r;
}

diag "Perl $]" if $ENV{TEST_VERBOSE};

# ===========================================================================
# 1. App::Project::Doctor::Finding
# ===========================================================================

require_ok 'App::Project::Doctor::Finding';

subtest 'Finding::new -- defaults' => sub {
	# When only message is supplied the other fields should carry documented
	# defaults so callers can safely omit them.
	my $f = App::Project::Doctor::Finding->new(message => 'ok');
	is  $f->severity,   $INFO_SEV,  'default severity is info';
	is  $f->detail,     $EMPTY,     'default detail is empty string';
	is  $f->check_name, 'Unknown',  'default check_name is Unknown';
	is  $f->file,       $EMPTY,     'default file is empty string';
	ok !defined $f->line,           'line undef by default';
};

subtest 'Finding::new -- all attributes round-trip' => sub {
	my $fix_called = 0;
	my $f = App::Project::Doctor::Finding->new(
		severity   => $ERR_SEV,
		message    => 'Something broke',
		detail     => 'Extra info',
		fix        => sub { $fix_called++ },
		check_name => 'Tests',
		file       => 'lib/Foo.pm',
		line       => 42,



( run in 0.749 second using v1.01-cache-2.11-cpan-af0e5977854 )