App-GHGen
view release on metacpan or search on metacpan
t/extended_tests.t view on Meta::CPAN
my $step = App::GHGen::Fixer::detect_and_create_cache_step($steps);
ok(defined $step, 'cache step created for Go project');
like($step->{with}{path}, qr|go/pkg/mod|, 'Go cache uses ~/go/pkg/mod path');
like($step->{with}{key}, qr/go\.sum/, 'Go cache key hashes go.sum');
};
subtest 'Fixer::detect_and_create_cache_step - setup-go action triggers Go cache' => sub {
my $steps = [{ uses => 'actions/setup-go@v5' }];
my $step = App::GHGen::Fixer::detect_and_create_cache_step($steps);
ok(defined $step, 'setup-go action triggers Go cache creation');
like($step->{with}{path}, qr|go/pkg/mod|, 'correct path for setup-go');
};
subtest 'Fixer::detect_and_create_cache_step - no matching steps returns undef' => sub {
# Branch: none of the known patterns â return undef.
my $steps = [{ run => 'echo hello' }];
my $step = App::GHGen::Fixer::detect_and_create_cache_step($steps);
is($step, undef, 'unrecognised steps produce no cache step');
};
subtest 'Fixer::add_caching - job already with cache step is skipped' => sub {
# LCSAJ: $has_cache is true â next â $modified stays 0.
my $wf = {
jobs => {
build => {
steps => [
{ uses => "$CACHE_ACTION\@v5" },
{ run => 'npm ci' },
],
},
},
};
my $result = App::GHGen::Fixer::add_caching($wf);
is($result, 0, 'job already with cache skipped; count stays 0');
};
subtest 'Fixer::add_trigger_filters - HASH on with push as bare string (truthy scalar)' => sub {
# Branch: ref $on->{push} eq '' with a truthy value â expand push to branches filter.
# Note: the implementation tests $on->{push} && ref $on->{push} eq '', so the
# scalar must be truthy (empty string is falsy and falls through).
my $wf = { on => { push => '*' }, jobs => {} };
my $n = App::GHGen::Fixer::add_trigger_filters($wf);
is($n, 1, 'truthy scalar push value gets expanded');
is(ref $wf->{on}{push}, 'HASH', 'push is now a HASH with filters');
is_deeply($wf->{on}{push}{branches}, ['main', 'master'], 'default branches added');
};
subtest 'Fixer::add_trigger_filters - no on key returns 0' => sub {
my $wf = { jobs => {} };
my $n = App::GHGen::Fixer::add_trigger_filters($wf);
is($n, 0, 'missing on key returns 0 modifications');
};
subtest 'Fixer::update_runners - windows-2016 upgraded to windows-latest' => sub {
my $wf = {
jobs => {
build => { 'runs-on' => 'windows-2016', steps => [] },
},
};
my $n = App::GHGen::Fixer::update_runners($wf);
is($n, 1, 'one runner updated');
is($wf->{jobs}{build}{'runs-on'}, 'windows-latest', 'windows-2016 â windows-latest');
};
subtest 'Fixer::update_runners - runner not in update table is unchanged' => sub {
my $wf = { jobs => { build => { 'runs-on' => 'ubuntu-latest', steps => [] } } };
my $n = App::GHGen::Fixer::update_runners($wf);
is($n, 0, 'current runner string produces no modifications');
};
subtest 'Fixer::get_latest_version - unknown action returns fallback v4' => sub {
# POD: unknown action â 'v4' fallback.
my $ver = App::GHGen::Fixer::get_latest_version('some/unknown-action');
is($ver, 'v4', 'unknown action returns v4 fallback');
};
subtest 'Fixer::apply_fixes - security/permissions branch fires add_permissions' => sub {
# Route to add_permissions via apply_fixes.
my $wf = { jobs => { build => { steps => [] } } };
my @issues = ({ type => $ISSUE_TYPE{SEC}, message => 'Missing permissions block' });
my $n = apply_fixes($wf, \@issues);
is($n, 1, 'one fix applied');
ok(exists $wf->{permissions}, 'permissions key inserted');
is($wf->{permissions}{contents}, 'read', 'contents: read set');
};
subtest 'Fixer::apply_fixes - maintenance/outdated action branch fires update_actions' => sub {
my $wf = {
jobs => {
build => {
steps => [{ uses => 'actions/cache@v3' }],
},
},
};
my @issues = ({ type => $ISSUE_TYPE{MAINT}, message => '1 outdated action(s)' });
my $n = apply_fixes($wf, \@issues);
is($n, 1, 'one action updated');
is($wf->{jobs}{build}{steps}[0]{uses}, 'actions/cache@v5', 'cache upgraded to v5');
};
subtest 'Fixer::apply_fixes - performance/missing timeout fires add_missing_timeout' => sub {
my $wf = {
jobs => {
build => { 'runs-on' => 'ubuntu-latest', steps => [] },
},
};
my @issues = ({
type => $ISSUE_TYPE{PERF},
message => "Job 'build' is missing timeout-minutes",
});
my $n = apply_fixes($wf, \@issues);
is($n, 1, 'timeout fix applied');
is($wf->{jobs}{build}{'timeout-minutes'}, 30, 'default 30-minute timeout inserted');
};
subtest 'Fixer::apply_fixes - unfixable issue type is skipped silently' => sub {
# can_auto_fix returns 0 for unknown types; apply_fixes skips them.
my $wf = { jobs => {} };
my @issues = ({ type => 'unknown_type', message => 'something weird' });
my $n = apply_fixes($wf, \@issues);
is($n, 0, 'unfixable issue produces zero fixes');
};
# =============================================================================
# 5. App::GHGen::Generator â content of non-Perl workflow generators
# =============================================================================
subtest 'Generator::generate_workflow - node workflow has expected structure' => sub {
my $yaml = generate_workflow('node');
ok(defined $yaml, 'node workflow generated');
like($yaml, qr/^---/m, 'starts with YAML header');
like($yaml, qr/Node\.js CI/, 'contains workflow name');
like($yaml, qr/node-version/, 'uses node-version matrix');
like($yaml, qr/actions\/setup-node/, 'includes setup-node action');
like($yaml, qr/npm/, 'includes npm commands');
};
subtest 'Generator::generate_workflow - python workflow has expected structure' => sub {
my $yaml = generate_workflow('python');
like($yaml, qr/Python CI/, 'python workflow named correctly');
like($yaml, qr/python-version/, 'uses python-version matrix');
like($yaml, qr/setup-python/, 'includes setup-python action');
like($yaml, qr/pytest/, 'includes pytest command');
};
subtest 'Generator::generate_workflow - rust workflow has expected structure' => sub {
my $yaml = generate_workflow('rust');
like($yaml, qr/Rust CI/, 'rust workflow named correctly');
like($yaml, qr/cargo/, 'includes cargo commands');
like($yaml, qr/clippy/, 'includes clippy linting');
};
subtest 'Generator::generate_workflow - go workflow has expected structure' => sub {
my $yaml = generate_workflow('go');
like($yaml, qr/Go CI/, 'go workflow named correctly');
like($yaml, qr/setup-go/, 'includes setup-go action');
like($yaml, qr/go test/, 'includes go test command');
( run in 0.849 second using v1.01-cache-2.11-cpan-81fc1098f69 )