Files
ladill-frontdesk/tests/Feature/FrontdeskPhase7Test.php
T
isaaccladandCursor dfda39df6e
Deploy Ladill Frontdesk / deploy (push) Successful in 23s
Add custom company logo upload and simplify kiosk branding.
Show Ladill Frontdesk or uploaded logo top-left on kiosk; allow logo upload in onboarding and organization settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 21:49:17 +00:00

178 lines
5.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Http\Middleware\EnsurePlatformSession;
use App\Models\Branch;
use App\Models\Device;
use App\Models\Host;
use App\Models\Member;
use App\Models\Organization;
use App\Models\User;
use App\Models\Visit;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class FrontdeskPhase7Test extends TestCase
{
use RefreshDatabase;
protected User $user;
protected Organization $organization;
protected string $deviceToken;
protected function setUp(): void
{
parent::setUp();
$this->withoutMiddleware(EnsurePlatformSession::class);
$this->user = User::create([
'public_id' => 'phase7-user-001',
'name' => 'Phase7 User',
'email' => 'phase7@example.com',
]);
$this->organization = Organization::create([
'owner_ref' => $this->user->public_id,
'name' => 'Phase7 Org',
'slug' => 'phase7-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,
]);
Host::create([
'owner_ref' => $this->user->public_id,
'organization_id' => $this->organization->id,
'name' => 'Lobby Host',
'is_available' => true,
]);
$this->deviceToken = 'kiosk-test-token-'.str_repeat('x', 32);
}
public function test_admin_can_register_kiosk_device(): void
{
$this->actingAs($this->user)
->post(route('frontdesk.devices.store'), [
'name' => 'Lobby Kiosk',
'type' => 'kiosk',
])
->assertRedirect(route('frontdesk.devices.index'));
$device = Device::first();
$this->assertSame('kiosk', $device->type);
$this->assertNotEmpty($device->device_token);
}
public function test_kiosk_device_page_works_without_auth(): void
{
$device = $this->createKioskDevice();
$this->get(route('frontdesk.kiosk.device', $device->device_token))
->assertOk()
->assertSee('Visitor Check-in')
->assertSee('Welcome to')
->assertSee('Tap to begin');
$this->assertTrue($device->fresh()->isOnline());
}
public function test_kiosk_device_page_shows_custom_organization_logo(): void
{
Storage::fake('public');
$path = UploadedFile::fake()->image('brand.png', 320, 80)->store('frontdesk/organizations/'.$this->organization->id, 'public');
$this->organization->update(['logo_path' => $path]);
$device = $this->createKioskDevice();
$this->get(route('frontdesk.kiosk.device', $device->device_token))
->assertOk()
->assertSee(Storage::disk('public')->url($path), false);
}
public function test_kiosk_device_can_check_in_visitor(): void
{
$device = $this->createKioskDevice();
$host = Host::first();
$this->postJson(route('frontdesk.kiosk.device.check-in', $device->device_token), [
'full_name' => 'Kiosk Guest',
'host_id' => $host->id,
'visitor_type' => 'visitor',
'policies_accepted' => 1,
])->assertOk()
->assertJsonPath('visit.visitor_name', 'Kiosk Guest');
$visit = Visit::first();
$this->assertSame(Visit::STATUS_CHECKED_IN, $visit->status);
$this->assertSame($device->branch_id, $visit->branch_id);
}
public function test_device_heartbeat_api_marks_online(): void
{
$device = $this->createKioskDevice(['status' => 'offline', 'last_online_at' => null]);
$this->postJson('/api/devices/heartbeat', [], [
'X-Device-Token' => $device->device_token,
])->assertOk()
->assertJsonPath('status', 'online');
$this->assertTrue($device->fresh()->isOnline());
}
public function test_mark_devices_offline_command(): void
{
Carbon::setTestNow(now());
$device = $this->createKioskDevice([
'status' => 'online',
'last_online_at' => now()->subMinutes(30),
]);
$this->artisan('frontdesk:mark-devices-offline')->assertSuccessful();
$this->assertSame('offline', $device->fresh()->status);
Carbon::setTestNow();
}
public function test_invalid_device_token_returns_not_found(): void
{
$this->get(route('frontdesk.kiosk.device', 'invalid-token'))
->assertNotFound();
}
/** @param array<string, mixed> $overrides */
protected function createKioskDevice(array $overrides = []): Device
{
return Device::create(array_merge([
'owner_ref' => $this->user->public_id,
'organization_id' => $this->organization->id,
'branch_id' => Branch::first()->id,
'name' => 'Test Kiosk',
'type' => 'kiosk',
'status' => 'offline',
'device_token' => $this->deviceToken,
'config' => ['mode' => 'self_service'],
], $overrides));
}
}