withoutMiddleware(EnsurePlatformSession::class); $this->user = User::create([ 'public_id' => 'test-user-notify', 'name' => 'Admin', 'email' => 'admin-notify@example.com', ]); $this->organization = Organization::create([ 'owner_ref' => $this->user->public_id, 'name' => 'Notify Clinic', 'slug' => 'notify-clinic', 'timezone' => 'UTC', 'settings' => [ 'onboarded' => true, 'facility_type' => 'clinic', 'notify_appointment_booked_sms' => true, 'notify_appointment_booked_email' => true, ], ]); Member::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $this->user->public_id, 'role' => 'hospital_admin', ]); $this->branch = Branch::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'name' => 'Main', 'is_active' => true, ]); Department::create([ 'owner_ref' => $this->user->public_id, 'branch_id' => $this->branch->id, 'name' => 'OPD', 'type' => 'outpatient', 'is_active' => true, ]); $this->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-NOT-00001', 'first_name' => 'Kofi', 'last_name' => 'Mensah', 'phone' => '+233201111111', 'email' => 'kofi@example.com', ]); $this->practitioner = Practitioner::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'name' => 'Dr. Asante', 'specialty' => 'GP', 'is_active' => true, ]); $smsKey = 'lsk_sms_live_'.str_repeat('n', 32); $birdKey = 'lsk_live_'.str_repeat('n', 32); MessagingCredential::create([ 'owner_ref' => $this->user->public_id, 'organization_id' => $this->organization->id, 'sms_api_key_encrypted' => Crypt::encryptString($smsKey), 'sms_api_key_prefix' => substr($smsKey, 0, 16), 'sms_sender_id' => 'Clinic', 'sms_status' => MessagingCredential::STATUS_VALID, 'sms_validated_at' => now(), 'bird_api_key_encrypted' => Crypt::encryptString($birdKey), 'bird_api_key_prefix' => substr($birdKey, 0, 16), 'bird_from_email' => 'clinic@example.test', 'bird_from_name' => 'Notify Clinic', 'bird_status' => MessagingCredential::STATUS_VALID, 'bird_validated_at' => now(), ]); } public function test_booking_sends_sms_and_email_when_enabled(): void { Http::fake([ '*/api/sms/send' => Http::response(['success' => true, 'message_id' => 1]), '*/api/smtp/send' => Http::response(['success' => true, 'message_id' => 'x']), ]); $this->actingAs($this->user) ->post(route('care.appointments.store'), [ 'branch_id' => $this->branch->id, 'patient_id' => $this->patient->id, 'practitioner_id' => $this->practitioner->id, 'scheduled_at' => now()->addDay()->format('Y-m-d\TH:i'), 'reason' => 'Check-up', ]) ->assertRedirect(); Http::assertSent(fn ($request) => str_contains($request->url(), '/api/sms/send')); Http::assertSent(fn ($request) => str_contains($request->url(), '/api/smtp/send')); $this->assertDatabaseHas('care_audit_logs', ['action' => 'appointment.booked_sms_sent']); $this->assertDatabaseHas('care_audit_logs', ['action' => 'appointment.booked_email_sent']); } public function test_booking_skips_notifications_when_disabled(): void { $this->organization->update([ 'settings' => [ 'onboarded' => true, 'facility_type' => 'clinic', 'notify_appointment_booked_sms' => false, 'notify_appointment_booked_email' => false, ], ]); Http::fake(); $this->actingAs($this->user) ->post(route('care.appointments.store'), [ 'branch_id' => $this->branch->id, 'patient_id' => $this->patient->id, 'practitioner_id' => $this->practitioner->id, 'scheduled_at' => now()->addDay()->format('Y-m-d\TH:i'), ]) ->assertRedirect(); Http::assertNothingSent(); } public function test_settings_can_persist_notification_toggles(): void { $this->actingAs($this->user) ->put(route('care.settings.update'), [ 'name' => 'Notify Clinic', 'timezone' => 'UTC', 'facility_type' => 'clinic', 'notify_appointment_booked_sms' => '1', 'notify_video_scheduled_email' => '1', ]) ->assertRedirect() ->assertSessionHas('success'); $this->organization->refresh(); $this->assertTrue((bool) data_get($this->organization->settings, 'notify_appointment_booked_sms')); $this->assertFalse((bool) data_get($this->organization->settings, 'notify_appointment_booked_email')); $this->assertTrue((bool) data_get($this->organization->settings, 'notify_video_scheduled_email')); $this->assertFalse((bool) data_get($this->organization->settings, 'notify_video_scheduled_sms')); } }