Files
fitness/tests/Feature/TrainerTest.php
T

200 lines
6.6 KiB
PHP
Raw Normal View History

2026-08-10 12:28:23 +03:00
<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Workout;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class TrainerTest extends TestCase
{
use RefreshDatabase;
protected function trainer(): User
{
$trainer = User::factory()->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();
}
}