clusev/tests/Feature/ReleasePageTest.php

135 lines
4.7 KiB
PHP

<?php
namespace Tests\Feature;
use App\Livewire\Release\Index;
use App\Models\AuditEvent;
use App\Models\User;
use App\Services\ReleaseBridge;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\RateLimiter;
use Livewire\Livewire;
use Tests\TestCase;
class ReleasePageTest extends TestCase
{
use RefreshDatabase;
private string $dir;
protected function setUp(): void
{
parent::setUp();
config()->set('clusev.release_controls', true);
config()->set('clusev.version', '0.9.58');
$this->actingAs(User::factory()->create(['must_change_password' => false]));
$this->dir = storage_path('app/restart-signal');
@mkdir($this->dir, 0775, true);
@unlink($this->dir.'/release-request.json');
}
protected function tearDown(): void
{
@unlink($this->dir.'/release-request.json');
foreach (glob($this->dir.'/release-result-*.json') ?: [] as $f) {
@unlink($f);
}
parent::tearDown();
}
public function test_deploy_staging_for_an_allowed_target_writes_a_request_and_audits(): void
{
Livewire::test(Index::class)->call('deployStaging', '0.10.0');
$payload = json_decode((string) file_get_contents($this->dir.'/release-request.json'), true);
$this->assertSame('stage', $payload['action']);
$this->assertSame('0.10.0', $payload['target']);
$this->assertTrue(AuditEvent::where('action', 'deploy.staging_release')->exists());
}
public function test_deploy_staging_rejects_a_target_not_in_the_allowed_set(): void
{
Livewire::test(Index::class)->call('deployStaging', '5.5.5');
$this->assertFileDoesNotExist($this->dir.'/release-request.json');
}
public function test_deploy_staging_is_throttled_per_user(): void
{
$key = 'release-stage:'.auth()->id();
for ($i = 0; $i < 3; $i++) {
RateLimiter::hit($key, 600);
}
Livewire::test(Index::class)->call('deployStaging', '0.10.0');
$this->assertFileDoesNotExist($this->dir.'/release-request.json');
}
public function test_poll_result_surfaces_a_success(): void
{
$c = Livewire::test(Index::class)->call('deployStaging', '0.10.0');
$id = $c->get('pendingId');
file_put_contents(
$this->dir."/release-result-{$id}.json",
json_encode(['id' => $id, 'ok' => true, 'tag' => 'v0.10.0-beta1', 'message' => 'ok'])
);
$c->call('pollResult')->assertSet('pendingId', null)->assertSee('v0.10.0-beta1');
}
public function test_poll_result_audits_a_host_failure_as_an_error(): void
{
$c = Livewire::test(Index::class)->call('deployStaging', '0.10.0');
$id = $c->get('pendingId');
file_put_contents(
$this->dir."/release-result-{$id}.json",
json_encode(['id' => $id, 'ok' => false, 'tag' => null, 'message' => 'dirty-tree'])
);
$c->call('pollResult')->assertSet('pendingId', null);
$this->assertTrue(AuditEvent::where('action', 'deploy.staging_release_failed')->exists());
}
public function test_mount_aborts_when_the_flag_is_off(): void
{
config()->set('clusev.release_controls', false);
Livewire::test(Index::class)->assertStatus(404);
}
public function test_render_includes_the_live_pipeline_for_a_beta(): void
{
config()->set('clusev.version', '0.9.61-beta1');
config()->set('clusev.staging_slug', ''); // degrade: no GitHub calls
config()->set('clusev.github_token', '');
Livewire::test(Index::class)
->assertViewHas('pipeline', fn ($p) => is_array($p) && $p['tag'] === 'v0.9.61-beta1');
}
public function test_render_pipeline_is_null_for_a_stable_version(): void
{
config()->set('clusev.version', '0.9.60');
Livewire::test(Index::class)->assertViewHas('pipeline', null);
}
public function test_save_test_server_persists_a_valid_url(): void
{
Livewire::test(Index::class)->call('saveTestServer', 'http://staging.local');
$this->assertSame('http://staging.local', \App\Models\Setting::get('pipeline_test_server'));
}
public function test_save_test_server_rejects_a_bad_url(): void
{
Livewire::test(Index::class)->call('saveTestServer', 'not-a-url');
$this->assertNull(\App\Models\Setting::get('pipeline_test_server'));
}
public function test_save_test_server_empty_clears_it(): void
{
\App\Models\Setting::put('pipeline_test_server', 'http://staging.local');
Livewire::test(Index::class)->call('saveTestServer', '');
$this->assertSame('', (string) \App\Models\Setting::get('pipeline_test_server', ''));
}
}