actingAs(User::factory()->create(['must_change_password' => false])); } public function test_action_label_maps_a_known_code(): void { // Default locale is German; the raw code maps to a readable label. $this->assertSame('WireGuard-Endpoint geändert', (new AuditEvent(['action' => 'wg.set-endpoint']))->action_label); } public function test_action_label_falls_back_to_a_tidied_form_for_unknown_codes(): void { // Dynamic harden.* codes are not individually mapped → tidied, never a bare machine code. $e = new AuditEvent(['action' => 'harden.ssh_password.off']); $this->assertSame('Harden · ssh password · off', $e->action_label); } public function test_is_error_flags_failure_and_security_events(): void { $this->assertTrue((new AuditEvent(['action' => 'auth.login_failed']))->is_error); $this->assertTrue((new AuditEvent(['action' => 'wg.action-failed']))->is_error); $this->assertFalse((new AuditEvent(['action' => 'wg.set-endpoint']))->is_error); } public function test_page_renders_the_readable_label_not_the_raw_code(): void { AuditEvent::create(['actor' => 'Administrator', 'action' => 'wg.set-endpoint', 'target' => '1.2.3.4:51820', 'ip' => '127.0.0.1']); Livewire::test(Index::class) ->assertSee('WireGuard-Endpoint geändert') ->assertDontSee('wg.set-endpoint'); } public function test_search_matches_the_readable_label(): void { AuditEvent::create(['actor' => 'Administrator', 'action' => 'wg.set-endpoint', 'target' => 'x', 'ip' => '127.0.0.1']); AuditEvent::create(['actor' => 'Administrator', 'action' => 'user.create', 'target' => 'y', 'ip' => '127.0.0.1']); Livewire::test(Index::class) ->set('q', 'Endpoint geändert') ->assertSee('WireGuard-Endpoint geändert') ->assertDontSee('Benutzer angelegt'); } public function test_paginates_the_audit_log_with_the_page_in_the_url(): void { for ($i = 0; $i < 30; $i++) { AuditEvent::create(['actor' => 'A', 'action' => 'user.create', 'target' => "t{$i}", 'ip' => '127.0.0.1', 'created_at' => now()->subMinutes($i)]); } Livewire::test(Index::class) ->assertViewHas('events', fn ($e) => $e->total() === 30 && $e->count() === 25 && $e->currentPage() === 1) ->call('gotoPage', 2) ->assertViewHas('events', fn ($e) => $e->currentPage() === 2 && $e->count() === 5); } public function test_changing_the_search_resets_to_the_first_page(): void { for ($i = 0; $i < 30; $i++) { AuditEvent::create(['actor' => 'A', 'action' => 'user.create', 'target' => "t{$i}", 'ip' => '127.0.0.1', 'created_at' => now()->subMinutes($i)]); } Livewire::test(Index::class) ->call('gotoPage', 2) ->set('q', 'user') ->assertViewHas('events', fn ($e) => $e->currentPage() === 1); } public function test_search_filters_in_sql_across_all_pages_not_just_one(): void { // 25 filler (fills page 1) + one older match that would otherwise sit on page 2 unfiltered. for ($i = 0; $i < 25; $i++) { AuditEvent::create(['actor' => 'A', 'action' => 'user.create', 'target' => "t{$i}", 'ip' => '127.0.0.1', 'created_at' => now()->subMinutes($i)]); } AuditEvent::create(['actor' => 'A', 'action' => 'wg.set-endpoint', 'target' => 'x', 'ip' => '127.0.0.1', 'created_at' => now()->subMinutes(99)]); Livewire::test(Index::class) ->set('q', 'Endpoint geändert') // label search → SQL-matches the single entry, now on page 1 ->assertViewHas('events', fn ($e) => $e->total() === 1) ->assertSee('WireGuard-Endpoint geändert'); } }