App-Project-Doctor

 view release on metacpan or  search on metacpan

t/extended_tests.t  view on Meta::CPAN

use Test::Mockingbird qw(mock_scoped restore_all);
use File::Temp qw(tempdir);
use File::Path qw(make_path);
use File::Spec;
use File::Basename qw(dirname);
use Scalar::Util qw(blessed);
use Readonly;

# ===========================================================================
# Constants
# ===========================================================================

Readonly::Scalar my $CONTEXT      => 'App::Project::Doctor::Context';
Readonly::Scalar my $FINDING      => 'App::Project::Doctor::Finding';
Readonly::Scalar my $REPORT       => 'App::Project::Doctor::Report';
Readonly::Scalar my $FIXER        => 'App::Project::Doctor::Fixer';
Readonly::Scalar my $DOCTOR       => 'App::Project::Doctor';
Readonly::Scalar my $GHACTIONS    => 'App::Project::Doctor::Check::GitHubActions';
Readonly::Scalar my $CHECK_POD    => 'App::Project::Doctor::Check::Pod';
Readonly::Scalar my $CHECK_SEC    => 'App::Project::Doctor::Check::Security';
Readonly::Scalar my $CHECK_CI     => 'App::Project::Doctor::Check::CI';
Readonly::Scalar my $CHECK_TESTS  => 'App::Project::Doctor::Check::Tests';

Readonly::Scalar my $SEV_ERROR    => 'error';
Readonly::Scalar my $SEV_WARN     => 'warning';
Readonly::Scalar my $SEV_PASS     => 'pass';
Readonly::Scalar my $SEV_INFO     => 'info';

Readonly::Scalar my $WORKFLOW_DIR => '.github/workflows';
Readonly::Scalar my $VALID_MSG    => 'Valid message for extended testing.';

# ===========================================================================
# Load modules under test
# ===========================================================================

use_ok $CONTEXT;
use_ok $FINDING;
use_ok $REPORT;
use_ok $FIXER;
use_ok $DOCTOR;
use_ok $GHACTIONS;
use_ok $CHECK_POD;
use_ok $CHECK_SEC;
use_ok $CHECK_CI;
use_ok $CHECK_TESTS;

# Check plugins inherit new() from Check::Base via 'use parent -norequire'.
# Base must be loaded explicitly because -norequire suppresses the automatic
# require that parent would normally issue.
require App::Project::Doctor::Check::Base;

# ===========================================================================
# Test helpers
# ===========================================================================

# Build a temporary distro directory from a hash of relative_path => content.
sub _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);
		make_path(dirname($abs)) unless -d dirname($abs);
		open my $fh, '>', $abs or die "Cannot write $abs: $!";
		print $fh $files{$rel};
		close $fh;
	}
	return $dir;
}

sub _ctx {
	my $dir = shift // tempdir(CLEANUP => 1);
	return $CONTEXT->new(root => $dir);
}

sub _f {
	my (%args) = @_;
	return $FINDING->new(
		message    => $VALID_MSG,
		check_name => 'ExtTest',
		severity   => $SEV_INFO,
		%args,
	);
}

sub _report_with {
	my @findings = @_;
	my $r = $REPORT->new;
	$r->add_findings(@findings) if @findings;
	return $r;
}

# ===========================================================================
# Check::GitHubActions -- previously 56% stmt / 33% branch / 0% cond
#
# Strategy: drive every branch by mocking App::Workflow::Lint and App::GHGen
# so tests run without network or real workflow files.
# ===========================================================================

subtest 'GitHubActions::check -- no .github/workflows/ dir returns info' => sub {
	# When the workflow directory is entirely absent the check returns an info
	# finding; it does NOT emit an error because Check::CI owns that signal.
	my $dir = _distro('Makefile.PL' => '');
	my @f = $GHACTIONS->new->check($CONTEXT->new(root => $dir));
	is(  scalar @f,   1,          'single finding' );
	is(  $f[0]->severity, $SEV_INFO, 'severity is info' );
	like($f[0]->message, qr/No .github.workflows/i, 'mentions absent dir' );
	ok(  !$f[0]->is_fixable, 'no fix when dir is absent' );
};

subtest 'GitHubActions::check -- empty workflows dir returns warning+fix' => sub {
	# .github/workflows/ present but no YAML files: warning with a fix that
	# generates a default workflow via App::GHGen.
	my $dir = _distro(
		'Makefile.PL'               => '',
		"$WORKFLOW_DIR/.gitkeep"    => '',    # forces the dir without any YAML
	);
	my @f = $GHACTIONS->new->check($CONTEXT->new(root => $dir));
	is(  scalar @f, 1,           'single finding' );
	is(  $f[0]->severity, $SEV_WARN, 'severity is warning' );
	ok(  $f[0]->is_fixable, 'fix is offered' );



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