Files
speedBB/tests/Unit/VersionReleaseCommandTest.php
tracer 88e4a70f88
Some checks failed
CI/CD Pipeline / test (push) Successful in 3s
CI/CD Pipeline / deploy (push) Failing after 15s
Add comprehensive test coverage and update notes
2026-02-08 19:04:12 +01:00

184 lines
6.0 KiB
PHP

<?php
namespace App\Console\Commands {
if (!function_exists(__NAMESPACE__ . '\\file_get_contents')) {
function file_get_contents($path): string|false
{
if (!empty($GLOBALS['version_release_file_get_contents_false']) && str_ends_with($path, 'CHANGELOG.md')) {
return false;
}
return \file_get_contents($path);
}
}
}
namespace {
use App\Console\Commands\VersionRelease;
use App\Models\Setting;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Http;
function withChangelogBackup(callable $callback): void
{
$path = base_path('CHANGELOG.md');
$had = file_exists($path);
$original = $had ? file_get_contents($path) : null;
try {
$callback($path);
} finally {
if ($had) {
file_put_contents($path, (string) $original);
} elseif (file_exists($path)) {
unlink($path);
}
}
}
function setGiteaEnvForRelease(): void
{
putenv('GITEA_TOKEN=token');
putenv('GITEA_OWNER=owner');
putenv('GITEA_REPO=repo');
putenv('GITEA_API_BASE=https://git.example.test/api/v1');
putenv('GITEA_PRERELEASE=false');
}
it('fails when version missing', function (): void {
Setting::where('key', 'version')->delete();
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(1);
});
it('fails when gitea config missing', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
putenv('GITEA_TOKEN');
putenv('GITEA_OWNER');
putenv('GITEA_REPO');
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(1);
});
it('creates release successfully with changelog body', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
setGiteaEnvForRelease();
withChangelogBackup(function (string $path): void {
file_put_contents($path, "# Changelog\n\n## 1.2.3\n- Added thing\n\n## 1.2.2\n- Old\n");
Http::fake([
'https://git.example.test/api/v1/repos/owner/repo/releases' => Http::response(['id' => 1], 201),
]);
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(0);
Http::assertSent(function ($request): bool {
$payload = $request->data();
return $payload['tag_name'] === 'v1.2.3'
&& str_contains($payload['body'], 'Added thing');
});
});
});
it('fails when create response is error', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
setGiteaEnvForRelease();
Http::fake([
'*' => Http::response([], 500),
]);
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(1);
});
it('fails when existing release cannot be fetched', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
setGiteaEnvForRelease();
Http::fake([
'https://git.example.test/api/v1/repos/owner/repo/releases' => Http::response([], 409),
'https://git.example.test/api/v1/repos/owner/repo/releases/tags/v1.2.3' => Http::response([], 500),
]);
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(1);
});
it('fails when existing release has no id', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
setGiteaEnvForRelease();
Http::fake([
'https://git.example.test/api/v1/repos/owner/repo/releases' => Http::response([], 409),
'https://git.example.test/api/v1/repos/owner/repo/releases/tags/v1.2.3' => Http::response(['id' => null], 200),
]);
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(1);
});
it('updates existing release when create conflicts', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
setGiteaEnvForRelease();
Http::fake([
'https://git.example.test/api/v1/repos/owner/repo/releases' => Http::response([], 409),
'https://git.example.test/api/v1/repos/owner/repo/releases/tags/v1.2.3' => Http::response(['id' => 99], 200),
'https://git.example.test/api/v1/repos/owner/repo/releases/99' => Http::response(['id' => 99], 200),
]);
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(0);
});
it('fails when updating existing release fails', function (): void {
Setting::updateOrCreate(['key' => 'version'], ['value' => '1.2.3']);
setGiteaEnvForRelease();
Http::fake([
'https://git.example.test/api/v1/repos/owner/repo/releases' => Http::response([], 422),
'https://git.example.test/api/v1/repos/owner/repo/releases/tags/v1.2.3' => Http::response(['id' => 99], 200),
'https://git.example.test/api/v1/repos/owner/repo/releases/99' => Http::response([], 500),
]);
$exitCode = Artisan::call('version:release');
expect($exitCode)->toBe(1);
});
it('returns default changelog body when file missing', function (): void {
withChangelogBackup(function (string $path): void {
if (file_exists($path)) {
unlink($path);
}
$command = new VersionRelease();
$ref = new ReflectionMethod($command, 'resolveChangelogBody');
$ref->setAccessible(true);
$body = $ref->invoke($command, '1.2.3');
expect($body)->toBe('See commit history for details.');
});
});
it('returns default changelog body when read fails', function (): void {
withChangelogBackup(function (string $path): void {
file_put_contents($path, "# Changelog\n\n## 1.2.3\n- Something\n");
$GLOBALS['version_release_file_get_contents_false'] = true;
$command = new VersionRelease();
$ref = new ReflectionMethod($command, 'resolveChangelogBody');
$ref->setAccessible(true);
$body = $ref->invoke($command, '1.2.3');
expect($body)->toBe('See commit history for details.');
$GLOBALS['version_release_file_get_contents_false'] = false;
});
});
}