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]); } }