withoutMiddleware(EnsurePlatformSession::class); $this->user = User::create([ 'public_id' => 'phase6-user-001', 'name' => 'Phase6 User', 'email' => 'phase6@example.com', ]); $this->organization = Organization::create([ 'owner_ref' => $this->user->public_id, 'name' => 'Phase6 Org', 'slug' => 'phase6-org', 'settings' => [ 'onboarded' => true, 'badge_expiry_hours' => 8, 'notification_channels' => ['email'], 'notification_events' => config('frontdesk.default_notification_events'), ], ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $this->user->public_id, 'role' => 'host', ]); Branch::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'name' => 'HQ', 'is_active' => true, ]); $this->host = Host::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'name' => 'Phase6 Host', 'email' => 'host@example.com', 'user_ref' => $this->user->public_id, 'is_available' => true, ]); } public function test_host_portal_lists_linked_profile(): void { $this->actingAs($this->user) ->get(route('frontdesk.host.index')) ->assertOk() ->assertSee('Phase6 Host'); } public function test_org_admin_without_linked_host_cannot_access_host_portal(): void { $admin = User::create([ 'public_id' => 'phase6-admin-001', 'name' => 'Org Admin', 'email' => 'admin@example.com', ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $admin->public_id, 'role' => 'org_admin', ]); $this->actingAs($admin) ->get(route('frontdesk.dashboard')) ->assertOk() ->assertDontSee('Host portal', false); $this->actingAs($admin) ->get(route('frontdesk.host.index')) ->assertRedirect(route('frontdesk.dashboard')) ->assertSessionHas('error'); } public function test_host_can_pre_register_visitor(): void { $this->actingAs($this->user) ->post(route('frontdesk.host.schedule.store'), [ 'full_name' => 'Expected Guest', 'visitor_type' => 'visitor', 'scheduled_at' => now()->addDay()->format('Y-m-d\TH:i'), 'purpose' => 'Project review', ]) ->assertRedirect(route('frontdesk.host.index')); $visit = Visit::first(); $this->assertSame($this->host->id, $visit->host_id); $this->assertSame('Expected Guest', $visit->visitor->full_name); $this->assertSame(Visit::STATUS_SCHEDULED, $visit->status); } public function test_host_can_approve_pending_visit(): void { $visitor = Visitor::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'full_name' => 'Vendor Rep', ]); $visit = Visit::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'visitor_id' => $visitor->id, 'host_id' => $this->host->id, 'visitor_type' => 'vendor', 'status' => Visit::STATUS_WAITING, 'policies_accepted' => true, 'contractor_details' => [ 'vendor_company' => 'Acme', 'service_type' => 'IT', '_awaiting_approval' => true, ], ]); $this->actingAs($this->user) ->post(route('frontdesk.host.approve', $visit)) ->assertRedirect(route('frontdesk.host.index')); $this->assertSame(Visit::STATUS_CHECKED_IN, $visit->fresh()->status); } public function test_check_in_notifies_linked_host_via_database(): void { Notification::fake(); $admin = User::create([ 'public_id' => 'phase6-admin-001', 'name' => 'Admin', 'email' => 'admin@example.com', ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $admin->public_id, 'role' => 'org_admin', ]); $this->actingAs($admin) ->post(route('frontdesk.visits.store'), [ 'full_name' => 'Walk-in Guest', 'host_id' => $this->host->id, 'visitor_type' => 'visitor', 'policies_accepted' => '1', ]) ->assertRedirect(); Notification::assertSentTo($this->user, FrontdeskAlertNotification::class); } public function test_disabled_notification_event_skips_host_alert(): void { Notification::fake(); $this->organization->update([ 'settings' => array_merge($this->organization->settings ?? [], [ 'notification_events' => array_merge( config('frontdesk.default_notification_events'), ['visitor_arrived' => false], ), ]), ]); $admin = User::create([ 'public_id' => 'phase6-admin-002', 'name' => 'Admin Two', 'email' => 'admin2@example.com', ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $admin->public_id, 'role' => 'org_admin', ]); $this->actingAs($admin) ->post(route('frontdesk.visits.store'), [ 'full_name' => 'Silent Guest', 'host_id' => $this->host->id, 'visitor_type' => 'visitor', 'policies_accepted' => '1', ]) ->assertRedirect(); Notification::assertNotSentTo($this->user, FrontdeskAlertNotification::class); } public function test_host_can_toggle_availability(): void { $this->actingAs($this->user) ->post(route('frontdesk.host.availability')) ->assertRedirect(); $this->assertFalse($this->host->fresh()->is_available); } }