clusev/tests/Feature/CertsComponentTest.php

113 lines
3.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Livewire\Certs\Index;
use App\Models\CertEndpoint;
use App\Models\User;
use App\Services\CertService;
use App\Support\Confirm\ConfirmToken;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Mockery;
use Tests\TestCase;
class CertsComponentTest extends TestCase
{
use RefreshDatabase;
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
private function operator(): User
{
return User::factory()->operator()->create(['must_change_password' => false]);
}
private function viewer(): User
{
return User::factory()->viewer()->create(['must_change_password' => false]);
}
public function test_viewer_cannot_open_certs(): void
{
$this->actingAs($this->viewer())->get('/certs')->assertForbidden();
}
public function test_operator_can_open_certs(): void
{
$this->actingAs($this->operator())->get('/certs')->assertOk();
}
public function test_operator_adds_an_endpoint_and_it_is_audited(): void
{
$this->actingAs($this->operator());
Livewire::test(Index::class)
->set('label', 'Panel')
->set('host', 'panel.example.com')
->set('port', 443)
->call('addEndpoint')
->assertHasNoErrors();
$this->assertDatabaseHas('cert_endpoints', ['host' => 'panel.example.com', 'port' => 443]);
$this->assertDatabaseHas('audit_events', ['action' => 'cert.endpoint_add']);
}
public function test_add_rejects_a_host_with_a_scheme_or_metacharacters(): void
{
$this->actingAs($this->operator());
Livewire::test(Index::class)
->set('host', 'https://evil.com/;rm -rf')
->set('port', 443)
->call('addEndpoint')
->assertHasErrors('host');
$this->assertDatabaseCount('cert_endpoints', 0);
}
public function test_add_rejects_an_out_of_range_port(): void
{
$this->actingAs($this->operator());
Livewire::test(Index::class)
->set('host', 'ok.example.com')
->set('port', 99999)
->call('addEndpoint')
->assertHasErrors('port');
}
public function test_scan_checks_each_endpoint(): void
{
$this->actingAs($this->operator());
CertEndpoint::create(['host' => 'svc.example.com', 'port' => 443]);
$certs = Mockery::mock(CertService::class);
$certs->shouldReceive('check')->once()->andReturn(['ok' => true, 'subject' => 'svc.example.com', 'issuer' => 'LE', 'expiresAt' => time() + 5 * 86400, 'daysLeft' => 5]);
$certs->shouldReceive('status')->once()->with(5)->andReturn('critical');
app()->instance(CertService::class, $certs);
Livewire::test(Index::class)
->call('scan')
->assertOk()
->assertSet('ready', true)
->assertSee(__('certs.status_critical'));
}
public function test_operator_deletes_an_endpoint_via_a_confirmed_token(): void
{
$this->actingAs($this->operator());
$ep = CertEndpoint::create(['host' => 'gone.example.com', 'port' => 443]);
$token = ConfirmToken::issue('certEndpointDeleted', ['uuid' => $ep->uuid], 'cert.endpoint_delete', $ep->host, null);
ConfirmToken::confirm($token);
Livewire::test(Index::class)->call('deleteEndpoint', $token)->assertOk();
$this->assertDatabaseMissing('cert_endpoints', ['id' => $ep->id]);
}
}