create(['level' => UserEnum::Doctor->value]); } public function test_routes_require_authentication(): void { $shift = Shift::factory()->create(); $this->get(route('dashboard.shifts.index'))->assertRedirect(route('login')); $this->put(route('dashboard.shifts.update', $shift))->assertRedirect(route('login')); $this->delete(route('dashboard.shifts.destroy', $shift))->assertRedirect(route('login')); } public function test_routes_are_forbidden_for_non_doctors(): void { $vet = User::factory()->create(['level' => UserEnum::Vet->value]); $shift = Shift::factory()->create(); $this->actingAs($vet)->get(route('dashboard.shifts.index'))->assertForbidden(); $this->actingAs($vet)->put(route('dashboard.shifts.update', $shift))->assertForbidden(); $this->actingAs($vet)->delete(route('dashboard.shifts.destroy', $shift))->assertForbidden(); } public function test_index_lists_my_shifts_and_open_upcoming_shifts_sorted(): void { Carbon::setTestNow('2026-09-21 10:00:00'); $doctor = $this->doctor(); $mine = Shift::factory()->weekly(ShiftDayEnum::Monday)->forDoctor($doctor)->create(); Shift::factory()->weekly(ShiftDayEnum::Monday)->forDoctor()->create(); $openLater = Shift::factory()->onDate('2026-09-25')->create(); $openWeekly = Shift::factory()->weekly(ShiftDayEnum::Saturday)->create(); Shift::factory()->onDate('2026-09-20')->create(); Shift::factory()->weekly(ShiftDayEnum::Sunday)->inactive()->create(); $this->actingAs($doctor)->get(route('dashboard.shifts.index')) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('Dashboard/Shifts/Index') ->has('myShifts.data', 1) ->where('myShifts.data.0.id', $mine->id) ->has('openShifts.data', 2) ->where('openShifts.data.0.id', $openWeekly->id) ->where('openShifts.data.1.id', $openLater->id)); } public function test_update_claims_open_shift(): void { $doctor = $this->doctor(); $shift = Shift::factory()->onDate('2026-09-21')->create(); $this->actingAs($doctor)->put(route('dashboard.shifts.update', $shift))->assertOk(); $this->assertDatabaseHas('shifts', ['id' => $shift->id, 'user_id' => $doctor->id]); } public function test_update_rejects_taken_shift(): void { $shift = Shift::factory()->onDate('2026-09-21')->forDoctor()->create(); $this->actingAs($this->doctor())->putJson(route('dashboard.shifts.update', $shift))->assertUnprocessable()->assertJsonValidationErrors('shift'); } public function test_destroy_releases_own_shift(): void { $doctor = $this->doctor(); $shift = Shift::factory()->onDate('2026-09-21')->forDoctor($doctor)->create(); $this->actingAs($doctor)->delete(route('dashboard.shifts.destroy', $shift))->assertOk(); $this->assertDatabaseHas('shifts', ['id' => $shift->id, 'user_id' => null]); } public function test_destroy_rejects_another_doctors_shift(): void { $shift = Shift::factory()->onDate('2026-09-21')->forDoctor()->create(); $this->actingAs($this->doctor())->deleteJson(route('dashboard.shifts.destroy', $shift))->assertUnprocessable(); $this->assertNotNull($shift->fresh()->user_id); } }