withoutMiddleware(EnsurePlatformSession::class); $this->owner = User::create([ 'public_id' => 'access-owner', 'name' => 'Owner', 'email' => 'access-owner@example.com', ]); $this->organization = Organization::create([ 'owner_ref' => $this->owner->public_id, 'name' => 'Access Clinic', 'slug' => 'access-clinic', 'settings' => [ 'onboarded' => true, 'facility_type' => 'clinic', 'plan' => 'pro', 'plan_expires_at' => now()->addMonth()->toIso8601String(), 'queue_integration_enabled' => true, ], ]); Member::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $this->owner->public_id, 'role' => 'hospital_admin', ]); $this->branch = Branch::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'name' => 'Main', 'is_active' => true, ]); $this->modules = app(SpecialtyModuleService::class); $this->modules->ensureDefaultModulesProvisioned($this->organization, $this->owner->public_id); foreach (['cardiology', 'infusion', 'pathology', 'dentistry'] as $key) { $this->modules->activate($this->organization->fresh(), $this->owner->public_id, $key); } $this->organization->refresh(); } protected function makeStaff(string $role, string $suffix): array { $user = User::create([ 'public_id' => 'access-'.$suffix, 'name' => ucfirst($role).' '.$suffix, 'email' => $suffix.'@example.com', ]); $member = Member::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $user->public_id, 'role' => $role, 'branch_id' => $this->branch->id, ]); return [$user, $member]; } public function test_nurse_and_pharmacist_manage_general_modules(): void { [, $nurse] = $this->makeStaff('nurse', 'nurse1'); [, $pharmacist] = $this->makeStaff('pharmacist', 'rx1'); [, $lab] = $this->makeStaff('lab_technician', 'lab1'); $this->assertTrue($this->modules->memberCanManage($this->organization, $nurse, 'emergency')); $this->assertTrue($this->modules->memberCanManage($this->organization, $pharmacist, 'emergency')); $this->assertTrue($this->modules->memberCanManage($this->organization, $pharmacist, 'infusion')); $this->assertTrue($this->modules->memberCanManage($this->organization, $lab, 'pathology')); $this->assertTrue($this->modules->memberCanManage($this->organization, $lab, 'blood_bank')); $this->assertFalse($this->modules->memberCanManage($this->organization, $pharmacist, 'cardiology')); } public function test_gp_doctor_manages_general_but_only_views_restricted(): void { [$doctor, $member] = $this->makeStaff('doctor', 'gp1'); Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'member_id' => $member->id, 'user_ref' => $doctor->public_id, 'name' => 'Dr GP', 'specialty' => 'General Practice', 'is_active' => true, ]); $this->assertTrue($this->modules->memberCanManage($this->organization, $member, 'emergency')); $this->assertTrue($this->modules->memberCanManage($this->organization, $member, 'dentistry')); $this->assertFalse($this->modules->memberCanManage($this->organization, $member, 'cardiology')); $this->assertTrue($this->modules->memberCanView($this->organization, $member, 'cardiology')); $this->assertTrue($this->modules->memberCanRefer($this->organization, $member, 'cardiology')); $this->assertSame('refer', $this->modules->memberAccessLevel($this->organization, $member, 'cardiology')); } public function test_cardiologist_manages_restricted_cardiology(): void { [$doctor, $member] = $this->makeStaff('doctor', 'cardio1'); $dept = Department::query()->where('type', 'cardiology')->firstOrFail(); Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'department_id' => $dept->id, 'member_id' => $member->id, 'user_ref' => $doctor->public_id, 'name' => 'Dr Cardio', 'specialty' => 'Cardiology', 'is_active' => true, ]); $this->assertTrue($this->modules->memberCanManage($this->organization, $member, 'cardiology')); $this->assertSame('manage', $this->modules->memberAccessLevel($this->organization, $member, 'cardiology')); } public function test_gp_can_refer_into_restricted_specialty_queue(): void { [$doctor, $member] = $this->makeStaff('doctor', 'gp2'); Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'member_id' => $member->id, 'user_ref' => $doctor->public_id, 'name' => 'Dr GP2', 'specialty' => 'General Practice', 'is_active' => true, ]); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-REF-1', 'first_name' => 'Ama', 'last_name' => 'Refer', 'gender' => 'female', 'date_of_birth' => '1990-01-01', ]); $this->actingAs($doctor) ->post(route('care.specialty.refer', 'cardiology'), [ 'patient_id' => $patient->id, 'branch_id' => $this->branch->id, 'reason' => 'Chest pain review', ]) ->assertRedirect(route('care.queue.index')); $this->assertDatabaseHas('care_appointments', [ 'patient_id' => $patient->id, 'reason' => 'Chest pain review', 'status' => Appointment::STATUS_WAITING, ]); } public function test_gp_cannot_save_clinical_on_restricted_module(): void { [$doctor, $member] = $this->makeStaff('doctor', 'gp3'); Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'member_id' => $member->id, 'user_ref' => $doctor->public_id, 'name' => 'Dr GP3', 'specialty' => 'General Practice', 'is_active' => true, ]); $dept = Department::query()->where('type', 'cardiology')->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-CARD-1', 'first_name' => 'Kofi', 'last_name' => 'Heart', 'gender' => 'male', 'date_of_birth' => '1980-01-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_IN_CONSULTATION, 'scheduled_at' => now(), 'checked_in_at' => now(), 'started_at' => now(), ]); $this->actingAs($doctor) ->get(route('care.specialty.workspace', ['module' => 'cardiology', 'visit' => $visit, 'tab' => 'exam'])) ->assertOk() ->assertSee('view + refer') ->assertDontSee('Save record') ->assertDontSee('Call next') ->assertDontSee('Add to invoice') ->assertDontSee('Upload document') ->assertSee('Refer to specialty queue') ->assertDontSee( 'action="'.route('care.specialty.consultation.start', ['module' => 'cardiology', 'visit' => $visit], false).'"', false, ); $this->actingAs($doctor) ->post(route('care.specialty.clinical.save', ['module' => 'cardiology', 'visit' => $visit]), [ 'tab' => 'exam', 'payload' => [ 'chief_complaint' => 'Should not save', ], ]) ->assertForbidden(); } public function test_sidebar_and_dashboard_exclude_modules_with_no_access(): void { [$pharmacistUser, $pharmacistMember] = $this->makeStaff('pharmacist', 'rx-nav'); $enabledForMember = collect($this->modules->enabledModulesForMember($this->organization, $pharmacistMember)) ->pluck('key') ->all(); $this->assertContains('emergency', $enabledForMember); $this->assertContains('infusion', $enabledForMember); $this->assertNotContains('cardiology', $enabledForMember); $this->assertNotContains('dentistry', $enabledForMember); $this->actingAs($pharmacistUser) ->get(route('care.dashboard')) ->assertOk() ->assertSee('Emergency') ->assertDontSee('Cardiology'); } public function test_manage_role_still_sees_mutate_actions_on_restricted_module(): void { [$doctor, $member] = $this->makeStaff('doctor', 'cardio-ui'); $dept = Department::query()->where('type', 'cardiology')->firstOrFail(); Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'department_id' => $dept->id, 'member_id' => $member->id, 'user_ref' => $doctor->public_id, 'name' => 'Dr Cardio UI', 'specialty' => 'Cardiology', 'is_active' => true, ]); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-CARD-UI', 'first_name' => 'Abena', 'last_name' => 'Heart', 'gender' => 'female', 'date_of_birth' => '1985-01-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'checked_in_at' => now(), ]); $this->assertTrue($this->modules->memberCanManage($this->organization, $member, 'cardiology')); $this->actingAs($doctor) ->get(route('care.specialty.workspace', ['module' => 'cardiology', 'visit' => $visit])) ->assertOk() ->assertDontSee('view + refer') ->assertSee('Start'); } public function test_admin_keeps_full_manage_access(): void { $admin = Member::query()->where('user_ref', $this->owner->public_id)->firstOrFail(); $this->assertTrue($this->modules->memberCanManage($this->organization, $admin, 'cardiology')); $this->assertTrue($this->modules->memberCanManage($this->organization, $admin, 'emergency')); } /** * @return array{0: \App\Models\User, 1: Member, 2: \App\Models\Visit} */ protected function dentistryVisitForRole(string $role, string $suffix): array { [$user, $member] = $this->makeStaff($role, $suffix); if ($role === 'doctor') { Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'member_id' => $member->id, 'user_ref' => $user->public_id, 'name' => 'Dr '.$suffix, 'specialty' => 'Dentistry', 'is_active' => true, ]); } $dept = Department::query()->where('type', 'dental')->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-DEN-'.$suffix, 'first_name' => 'Efua', 'last_name' => 'Boateng', 'gender' => 'female', 'date_of_birth' => '1992-06-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), 'specialty_stage' => 'waiting', ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'checked_in_at' => now(), 'waiting_at' => now(), ]); return [$user, $member, $visit]; } /** * @return array{0: \App\Models\User, 1: Member, 2: \App\Models\Visit} */ protected function emergencyVisitForRole(string $role, string $suffix): array { [$user, $member] = $this->makeStaff($role, $suffix); $dept = Department::query()->where('type', 'emergency')->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-ER-'.$suffix, 'first_name' => 'Kojo', 'last_name' => 'Floor', 'gender' => 'male', 'date_of_birth' => '1988-01-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), 'specialty_stage' => 'arrival', ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'checked_in_at' => now(), 'waiting_at' => now(), ]); return [$user, $member, $visit]; } /** * Roles that can manage a specialty module but lack consultations.manage must not see * Start / stage / chart-mutate CTAs. Gating is ability-based — not nurse-hardcoded. * * @return list */ public static function floorRolesWithoutConsultManage(): array { return [ ['nurse', 'dentistry', 'floor-nurse-den'], ['receptionist', 'dentistry', 'floor-recv-den'], ['lab_technician', 'emergency', 'floor-lab-er'], ['pharmacist', 'emergency', 'floor-rx-er'], ]; } #[DataProvider('floorRolesWithoutConsultManage')] public function test_floor_roles_without_consult_do_not_see_mutate_ctas( string $role, string $module, string $suffix, ): void { [$user, $member, $visit] = $module === 'dentistry' ? $this->dentistryVisitForRole($role, $suffix) : $this->emergencyVisitForRole($role, $suffix); $permissions = app(\App\Services\Care\CarePermissions::class); $this->assertTrue($this->modules->memberCanManage($this->organization, $member, $module)); $this->assertFalse($permissions->can($member, 'consultations.manage')); // Prove gating is not nurse-only: same CTA rules for every floor role without consult. $this->assertNotSame('hospital_admin', $member->role); $html = $this->actingAs($user) ->get(route('care.specialty.workspace', ['module' => $module, 'visit' => $visit, 'tab' => 'overview'])) ->assertOk() ->assertSee('consultation access') ->assertDontSee('Seat at chair') ->assertDontSee('Start triage') ->assertSee('Back to queue') ->assertSee('Patient chart') ->getContent(); $this->assertStringNotContainsString( route('care.specialty.consultation.start', ['module' => $module, 'visit' => $visit], absolute: false), $html, ); if ($module === 'dentistry') { $this->assertStringNotContainsString( route('care.specialty.dentistry.stage', $visit, absolute: false), $html, ); $this->assertStringContainsString('Waiting', $html); } else { $this->assertStringNotContainsString( route('care.specialty.emergency.stage', $visit, absolute: false), $html, ); } if ($permissions->can($member, 'appointments.manage')) { $this->assertStringContainsString('Register / book', $html); } else { $this->assertStringNotContainsString('Register / book', $html); } } public function test_nurse_dentistry_mutate_posts_are_forbidden(): void { [$nurseUser, , $visit] = $this->dentistryVisitForRole('nurse', 'den-nurse-post'); $this->actingAs($nurseUser) ->post(route('care.specialty.dentistry.stage', $visit), ['stage' => 'chair']) ->assertForbidden(); $this->actingAs($nurseUser) ->post(route('care.specialty.consultation.start', ['module' => 'dentistry', 'visit' => $visit])) ->assertForbidden(); $this->actingAs($nurseUser) ->post(route('care.specialty.dentistry.tooth', $visit), [ 'tooth_code' => '16', 'status' => 'present', ]) ->assertForbidden(); } public function test_receptionist_dentistry_mutate_posts_are_forbidden(): void { [$user, , $visit] = $this->dentistryVisitForRole('receptionist', 'den-recv-post'); $this->actingAs($user) ->post(route('care.specialty.dentistry.stage', $visit), ['stage' => 'chair']) ->assertForbidden(); $this->actingAs($user) ->post(route('care.specialty.consultation.start', ['module' => 'dentistry', 'visit' => $visit])) ->assertForbidden(); } public function test_lab_technician_and_pharmacist_emergency_mutate_posts_are_forbidden(): void { foreach (['lab_technician' => 'lab-er-post', 'pharmacist' => 'rx-er-post'] as $role => $suffix) { [$user, , $visit] = $this->emergencyVisitForRole($role, $suffix); $this->actingAs($user) ->post(route('care.specialty.emergency.stage', $visit), ['stage' => 'treatment']) ->assertForbidden(); $this->actingAs($user) ->post(route('care.specialty.consultation.start', ['module' => 'emergency', 'visit' => $visit])) ->assertForbidden(); $this->actingAs($user) ->post(route('care.specialty.emergency.vitals', $visit), [ 'bp_systolic' => 120, 'bp_diastolic' => 80, 'pulse' => 72, ]) ->assertForbidden(); } } public function test_doctor_on_dentistry_sees_and_can_advance_stage(): void { [$doctorUser, $doctorMember, $visit] = $this->dentistryVisitForRole('doctor', 'den-doc'); $this->assertTrue($this->modules->memberCanManage($this->organization, $doctorMember, 'dentistry')); $this->assertTrue(app(\App\Services\Care\CarePermissions::class)->can($doctorMember, 'consultations.manage')); $this->actingAs($doctorUser) ->get(route('care.specialty.workspace', ['module' => 'dentistry', 'visit' => $visit, 'tab' => 'overview'])) ->assertOk() ->assertSee('Seat at chair') ->assertSee('Start') ->assertDontSee('consultation access'); $this->actingAs($doctorUser) ->post(route('care.specialty.dentistry.stage', $visit), ['stage' => 'chair']) ->assertRedirect(); $this->assertSame('chair', $visit->fresh()->specialty_stage); } public function test_gp_with_consult_ability_but_no_module_manage_hides_mutate_ctas(): void { [$doctor, $member] = $this->makeStaff('doctor', 'gp-no-manage'); Practitioner::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'member_id' => $member->id, 'user_ref' => $doctor->public_id, 'name' => 'Dr GP No Manage', 'specialty' => 'General Practice', 'is_active' => true, ]); $permissions = app(\App\Services\Care\CarePermissions::class); $this->assertTrue($permissions->can($member, 'consultations.manage')); $this->assertFalse($this->modules->memberCanManage($this->organization, $member, 'cardiology')); $this->assertSame('refer', $this->modules->memberAccessLevel($this->organization, $member, 'cardiology')); $dept = Department::query()->where('type', 'cardiology')->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-GP-NM', 'first_name' => 'Yaw', 'last_name' => 'ReferOnly', 'gender' => 'male', 'date_of_birth' => '1975-01-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'checked_in_at' => now(), 'waiting_at' => now(), ]); $html = $this->actingAs($doctor) ->get(route('care.specialty.workspace', ['module' => 'cardiology', 'visit' => $visit, 'tab' => 'overview'])) ->assertOk() ->assertSee('view + refer') ->assertDontSee('consultation access') ->assertDontSee('Seat at chair') ->assertDontSee('Start triage') ->getContent(); $this->assertStringNotContainsString( route('care.specialty.consultation.start', ['module' => 'cardiology', 'visit' => $visit], absolute: false), $html, ); $this->assertStringNotContainsString('>Start', $html); } public function test_admin_on_dentistry_sees_mutate_actions(): void { $dept = Department::query()->where('type', 'dental')->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-DEN-ADMIN', 'first_name' => 'Admin', 'last_name' => 'Patient', 'gender' => 'male', 'date_of_birth' => '1980-01-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), 'specialty_stage' => 'waiting', ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'checked_in_at' => now(), 'waiting_at' => now(), ]); $this->actingAs($this->owner) ->get(route('care.specialty.workspace', ['module' => 'dentistry', 'visit' => $visit, 'tab' => 'overview'])) ->assertOk() ->assertSee('Seat at chair') ->assertSee('Start'); } public function test_nurse_can_save_emergency_vitals_with_vitals_manage(): void { [$nurseUser, $nurseMember] = $this->makeStaff('nurse', 'er-vitals'); $this->assertTrue(app(\App\Services\Care\CarePermissions::class)->can($nurseMember, 'vitals.manage')); $this->assertFalse(app(\App\Services\Care\CarePermissions::class)->can($nurseMember, 'consultations.manage')); $dept = Department::query()->where('type', 'emergency')->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-ER-VITALS', 'first_name' => 'Kojo', 'last_name' => 'Mensah', 'gender' => 'male', 'date_of_birth' => '1988-01-01', ]); $visit = \App\Models\Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, 'checked_in_at' => now(), ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $dept->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_IN_CONSULTATION, 'scheduled_at' => now(), 'checked_in_at' => now(), 'started_at' => now(), ]); $this->actingAs($nurseUser) ->get(route('care.specialty.workspace', ['module' => 'emergency', 'visit' => $visit, 'tab' => 'vitals'])) ->assertOk() ->assertSee('Save vitals') ->assertDontSee('Seat at chair') ->assertDontSee('Start triage'); $this->actingAs($nurseUser) ->post(route('care.specialty.emergency.vitals', $visit), [ 'bp_systolic' => 120, 'bp_diastolic' => 80, 'pulse' => 72, ]) ->assertRedirect(); $this->actingAs($nurseUser) ->post(route('care.specialty.emergency.stage', $visit), ['stage' => 'treatment']) ->assertForbidden(); } }