withoutMiddleware(EnsurePlatformSession::class); $this->user = User::create([ 'public_id' => 'test-user-001', 'name' => 'Test User', 'email' => 'test@example.com', ]); $this->organization = Organization::create([ 'owner_ref' => $this->user->public_id, 'name' => 'Test Clinic', 'slug' => 'test-clinic', 'timezone' => 'UTC', 'settings' => ['onboarded' => true], ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $this->user->public_id, 'role' => 'receptionist', ]); $this->branch = Branch::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'name' => 'Main Branch', 'is_active' => true, ]); Department::create([ 'owner_ref' => $this->user->public_id, 'branch_id' => $this->branch->id, 'name' => 'General Outpatient', 'type' => 'outpatient', 'is_active' => true, ]); } public function test_patients_index_loads(): void { $this->actingAs($this->user) ->get(route('care.patients.index')) ->assertOk() ->assertSee('Patients'); } public function test_can_register_patient(): void { $this->actingAs($this->user) ->post(route('care.patients.store'), [ 'first_name' => 'Ama', 'last_name' => 'Mensah', 'phone' => '+233201234567', 'national_id' => 'GHA-123456789-0', 'gender' => 'female', 'date_of_birth' => '1990-05-15', 'branch_id' => $this->branch->id, 'allergies' => [ ['allergen' => 'Penicillin', 'severity' => 'severe'], ], 'emergency_contacts' => [ ['name' => 'Kofi Mensah', 'phone' => '+233209876543', 'is_primary' => true], ], ]) ->assertRedirect(); $patient = Patient::first(); $this->assertNotNull($patient); $this->assertSame('Ama Mensah', $patient->fullName()); $this->assertStringStartsWith('LC-', $patient->patient_number); $this->assertDatabaseHas('care_patient_allergies', ['allergen' => 'Penicillin']); $this->assertDatabaseHas('care_emergency_contacts', ['name' => 'Kofi Mensah']); $this->assertDatabaseHas('care_audit_logs', ['action' => 'patient.created']); } public function test_can_search_patients_by_phone(): void { Patient::create([ 'uuid' => (string) \Illuminate\Support\Str::uuid(), 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'LC-2026-00001', 'first_name' => 'Kwame', 'last_name' => 'Asante', 'phone' => '+233244111222', ]); $this->actingAs($this->user) ->get(route('care.patients.index', ['q' => '244111222'])) ->assertOk() ->assertSee('Kwame Asante'); } public function test_patient_dashboard_loads(): void { $patient = Patient::create([ 'uuid' => (string) \Illuminate\Support\Str::uuid(), 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'LC-2026-00001', 'first_name' => 'Efua', 'last_name' => 'Boateng', ]); $this->actingAs($this->user) ->get(route('care.patients.show', $patient)) ->assertOk() ->assertSee('Efua Boateng') ->assertSee('LC-2026-00001') ->assertSee('Message patient'); } public function test_can_send_patient_sms_via_customer_relay(): void { $plain = 'lsk_sms_live_'.str_repeat('e', 32); MessagingCredential::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'sms_api_key_encrypted' => Crypt::encryptString($plain), 'sms_api_key_prefix' => substr($plain, 0, 16), 'sms_sender_id' => 'ClinicA', 'sms_status' => MessagingCredential::STATUS_VALID, 'sms_validated_at' => now(), ]); config(['sms.customer_relay_url' => 'https://ladill.test/api/sms']); \Illuminate\Support\Facades\Http::fake([ 'ladill.test/api/sms/send' => \Illuminate\Support\Facades\Http::response([ 'success' => true, 'segments' => 1, ]), ]); $patient = Patient::create([ 'uuid' => (string) \Illuminate\Support\Str::uuid(), 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'LC-2026-00002', 'first_name' => 'Kofi', 'last_name' => 'Mensah', 'phone' => '0244111222', ]); $this->actingAs($this->user) ->post(route('care.patients.sms', $patient), [ 'message' => 'Your appointment is tomorrow at 9am.', ]) ->assertRedirect() ->assertSessionHas('success'); $this->assertDatabaseHas('care_audit_logs', ['action' => 'patient.sms_sent']); } public function test_can_send_patient_email_via_customer_relay(): void { $plain = 'lsk_live_'.str_repeat('f', 32); MessagingCredential::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'bird_api_key_encrypted' => Crypt::encryptString($plain), 'bird_api_key_prefix' => substr($plain, 0, 16), 'bird_from_email' => 'care@example.test', 'bird_from_name' => 'Ladill Care', 'bird_status' => MessagingCredential::STATUS_VALID, 'bird_validated_at' => now(), ]); config(['smtp.customer_relay_url' => 'https://ladill.test/api/smtp']); \Illuminate\Support\Facades\Http::fake([ 'ladill.test/api/smtp/send' => \Illuminate\Support\Facades\Http::response([ 'success' => true, 'message_id' => 'msg-1', ]), ]); $patient = Patient::create([ 'uuid' => (string) \Illuminate\Support\Str::uuid(), 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'LC-2026-00003', 'first_name' => 'Ama', 'last_name' => 'Serwaa', 'email' => 'ama@example.com', ]); $this->actingAs($this->user) ->post(route('care.patients.email', $patient), [ 'subject' => 'Appointment reminder', 'body' => 'Please arrive 15 minutes early.', ]) ->assertRedirect() ->assertSessionHas('success'); $this->assertDatabaseHas('care_audit_logs', ['action' => 'patient.email_sent']); } public function test_api_can_list_patients(): void { Patient::create([ 'uuid' => (string) \Illuminate\Support\Str::uuid(), 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'patient_number' => 'LC-2026-00001', 'first_name' => 'Api', 'last_name' => 'Patient', ]); Sanctum::actingAs($this->user); $this->getJson('/api/v1/patients') ->assertOk() ->assertJsonPath('data.0.first_name', 'Api'); } public function test_api_can_create_patient(): void { Sanctum::actingAs($this->user); $this->postJson('/api/v1/patients', [ 'first_name' => 'Yaa', 'last_name' => 'Owusu', 'phone' => '+233555000111', ]) ->assertCreated() ->assertJsonPath('first_name', 'Yaa'); $this->assertSame(1, Patient::count()); } public function test_doctor_cannot_register_patient(): void { Member::where('user_ref', $this->user->public_id)->update(['role' => 'doctor']); $this->actingAs($this->user) ->get(route('care.patients.create')) ->assertForbidden(); } }