withoutMiddleware(EnsurePlatformSession::class); $this->user = User::create([ 'public_id' => 'phase5-user-001', 'name' => 'Phase5 User', 'email' => 'phase5@example.com', ]); $this->organization = Organization::create([ 'owner_ref' => $this->user->public_id, 'name' => 'Phase5 Org', 'slug' => 'phase5-org', 'settings' => ['onboarded' => true, 'badge_expiry_hours' => 8], ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $this->user->public_id, 'role' => 'org_admin', ]); Branch::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'name' => 'HQ', 'is_active' => true, ]); } public function test_blacklisted_check_in_records_audit_log(): void { $visitor = Visitor::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'full_name' => 'Blocked Person', 'email' => 'blocked@example.com', 'watchlist_status' => Visitor::WATCHLIST_BLACKLISTED, ]); $this->actingAs($this->user) ->post(route('frontdesk.visits.store'), [ 'visitor_id' => $visitor->id, 'full_name' => 'Blocked Person', 'email' => 'blocked@example.com', 'visitor_type' => 'visitor', 'policies_accepted' => '1', ]) ->assertForbidden(); $this->assertDatabaseHas('frontdesk_audit_logs', [ 'action' => 'watchlist.blocked_attempt', ]); } public function test_flagged_visitor_check_in_queues_for_approval(): void { $visitor = Visitor::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'full_name' => 'Flagged Person', 'watchlist_status' => Visitor::WATCHLIST_REQUIRES_APPROVAL, ]); $this->actingAs($this->user) ->post(route('frontdesk.visitors.check-in.store', $visitor), [ 'visitor_type' => 'visitor', 'policies_accepted' => '1', ]) ->assertRedirect(); $visit = Visit::first(); $this->assertSame(Visit::STATUS_WAITING, $visit->status); $this->assertTrue($visit->awaitingApproval()); $this->assertDatabaseHas('frontdesk_audit_logs', [ 'action' => 'watchlist.flagged_checkin', ]); } public function test_watchlist_admin_can_create_entry(): void { $this->actingAs($this->user) ->post(route('frontdesk.watchlist.store'), [ 'full_name' => 'Known Person', 'status' => Visitor::WATCHLIST_BLACKLISTED, 'reason' => 'Previous incident', ]) ->assertRedirect(route('frontdesk.watchlist.index')); $this->assertDatabaseHas('frontdesk_watchlist_entries', [ 'full_name' => 'Known Person', 'status' => Visitor::WATCHLIST_BLACKLISTED, ]); } public function test_audit_log_page_loads_and_exports_csv(): void { AuditLog::record( $this->user->public_id, 'visit.checked_in', $this->organization->id, $this->user->public_id, Visit::class, 1, ['visitor' => 'Test'], ); $this->actingAs($this->user) ->get(route('frontdesk.audit.index')) ->assertOk() ->assertSee('Audit log'); $this->actingAs($this->user) ->get(route('frontdesk.audit.export')) ->assertOk() ->assertHeader('content-type', 'text/csv; charset=UTF-8'); } public function test_security_can_verify_badge_code(): void { $visitor = Visitor::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'full_name' => 'Verify Me', ]); $visit = Visit::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'visitor_id' => $visitor->id, 'visitor_type' => 'visitor', 'status' => Visit::STATUS_CHECKED_IN, 'badge_code' => 'ABC12345', 'checked_in_at' => now(), 'badge_expires_at' => now()->addHours(4), ]); $this->actingAs($this->user) ->post(route('frontdesk.security.verify.lookup'), ['lookup' => 'ABC12345']) ->assertOk() ->assertSee('Verify Me') ->assertSee('Valid'); } public function test_soft_deleted_visitor_can_be_restored(): void { $visitor = Visitor::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'full_name' => 'Archived Person', ]); $visitor->delete(); $this->actingAs($this->user) ->post(route('frontdesk.compliance.visitors.restore', $visitor->id)) ->assertRedirect(); $this->assertNull($visitor->fresh()->deleted_at); $this->assertDatabaseHas('frontdesk_audit_logs', ['action' => 'visitor.restored']); } public function test_expired_badge_command_logs_alert(): void { Carbon::setTestNow('2026-06-27 18:00:00'); $visitor = Visitor::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'full_name' => 'Expired Badge Guest', ]); Visit::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'visitor_id' => $visitor->id, 'visitor_type' => 'visitor', 'status' => Visit::STATUS_CHECKED_IN, 'checked_in_at' => now()->subHours(10), 'badge_expires_at' => now()->subHour(), 'badge_code' => 'EXP12345', ]); $this->artisan('frontdesk:mark-expired-badges')->assertSuccessful(); $this->assertDatabaseHas('frontdesk_audit_logs', ['action' => 'badge.expired']); Carbon::setTestNow(); } }