Add comprehensive test coverage and update notes
This commit is contained in:
183
tests/Unit/VersionReleaseCommandTest.php
Normal file
183
tests/Unit/VersionReleaseCommandTest.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?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;
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user