create(); $trainer->is_trainer = true; $trainer->save(); return $trainer; } public function test_guest_is_redirected_to_login(): void { $response = $this->get(route('trainer.clients')); $response->assertRedirect(route('login')); } public function test_non_trainer_is_forbidden(): void { $user = User::factory()->create(); $response = $this->actingAs($user)->get(route('trainer.clients')); $response->assertForbidden(); } public function test_trainer_can_add_a_client_by_email(): void { $trainer = $this->trainer(); $client = User::factory()->create(['email' => 'client@example.com']); $response = $this->actingAs($trainer)->post(route('trainer.clients.add'), [ 'email' => 'client@example.com', ]); $response->assertRedirect(); $this->assertTrue($trainer->clients()->where('client_id', $client->id)->exists()); } public function test_trainer_cannot_add_themselves_as_a_client(): void { $trainer = $this->trainer(); $response = $this->actingAs($trainer)->post(route('trainer.clients.add'), [ 'email' => $trainer->email, ]); $response->assertSessionHasErrors('email'); $this->assertFalse($trainer->clients()->where('client_id', $trainer->id)->exists()); } public function test_trainer_cannot_add_the_same_client_twice(): void { $trainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $response = $this->actingAs($trainer)->post(route('trainer.clients.add'), [ 'email' => $client->email, ]); $response->assertSessionHasErrors('email'); $this->assertEquals(1, $trainer->clients()->where('client_id', $client->id)->count()); } public function test_trainer_cannot_add_a_client_with_an_unknown_email(): void { $trainer = $this->trainer(); $response = $this->actingAs($trainer)->post(route('trainer.clients.add'), [ 'email' => 'nobody@example.com', ]); $response->assertSessionHasErrors('email'); } public function test_trainer_can_remove_a_client(): void { $trainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $response = $this->actingAs($trainer)->delete(route('trainer.clients.remove', $client)); $response->assertRedirect(); $this->assertFalse($trainer->clients()->where('client_id', $client->id)->exists()); } public function test_trainer_can_assign_a_workout_to_their_client(): void { $trainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $response = $this->actingAs($trainer)->post(route('trainer.workouts.store', $client), [ 'title' => 'Week 1 Push Day', ]); $response->assertRedirect(route('trainer.clients')); $this->assertDatabaseHas('workouts', [ 'user_id' => $client->id, 'assigned_by_trainer_id' => $trainer->id, 'title' => 'Week 1 Push Day', ]); } public function test_client_roster_lists_workouts_assigned_to_each_client(): void { $trainer = $this->trainer(); $client = User::factory()->create(['name' => 'Jamie Client']); $trainer->clients()->attach($client->id); Workout::factory()->create([ 'user_id' => $client->id, 'assigned_by_trainer_id' => $trainer->id, 'title' => 'Week 1 Push Day', ]); // A workout the client made for themselves should not show up as "assigned". Workout::factory()->create(['user_id' => $client->id, 'title' => 'My Own Workout']); $response = $this->actingAs($trainer)->get(route('trainer.clients')); $response->assertOk(); $response->assertSee('Week 1 Push Day'); $response->assertDontSee('My Own Workout'); } public function test_trainer_cannot_assign_a_workout_to_a_non_client(): void { $trainer = $this->trainer(); $stranger = User::factory()->create(); $response = $this->actingAs($trainer)->post(route('trainer.workouts.store', $stranger), [ 'title' => 'Week 1 Push Day', ]); $response->assertForbidden(); } public function test_client_can_manage_their_assigned_workout(): void { $trainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $workout = Workout::factory()->create(['user_id' => $client->id, 'assigned_by_trainer_id' => $trainer->id]); $response = $this->actingAs($client)->get(route('workouts.show', $workout)); $response->assertOk(); } public function test_assigning_trainer_can_view_and_edit_the_assigned_workout(): void { $trainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $workout = Workout::factory()->create(['user_id' => $client->id, 'assigned_by_trainer_id' => $trainer->id]); $response = $this->actingAs($trainer)->get(route('workouts.show', $workout)); $response->assertOk(); } public function test_assigning_trainer_cannot_delete_the_assigned_workout(): void { $trainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $workout = Workout::factory()->create(['user_id' => $client->id, 'assigned_by_trainer_id' => $trainer->id]); $response = $this->actingAs($trainer)->delete(route('workouts.destroy', $workout)); $response->assertForbidden(); $this->assertDatabaseHas('workouts', ['id' => $workout->id]); } public function test_unrelated_trainer_cannot_view_someone_elses_assigned_workout(): void { $trainer = $this->trainer(); $otherTrainer = $this->trainer(); $client = User::factory()->create(); $trainer->clients()->attach($client->id); $workout = Workout::factory()->create(['user_id' => $client->id, 'assigned_by_trainer_id' => $trainer->id]); $response = $this->actingAs($otherTrainer)->get(route('workouts.show', $workout)); $response->assertForbidden(); } }