2026-08-10 11:47:51 +03:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Tests\Feature;
|
|
|
|
|
|
|
|
|
|
use App\Models\BodyPart;
|
|
|
|
|
use App\Models\Exercise;
|
2026-08-10 12:15:14 +03:00
|
|
|
use App\Models\User;
|
|
|
|
|
use App\Models\Workout;
|
|
|
|
|
use App\Models\WorkoutExercise;
|
|
|
|
|
use App\Models\WorkoutSession;
|
|
|
|
|
use App\Models\WorkoutSessionItem;
|
2026-08-10 11:47:51 +03:00
|
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
|
use Tests\TestCase;
|
|
|
|
|
|
|
|
|
|
class ExerciseTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
use RefreshDatabase;
|
|
|
|
|
|
|
|
|
|
public function test_index_lists_exercises(): void
|
|
|
|
|
{
|
|
|
|
|
Exercise::factory()->count(3)->create();
|
|
|
|
|
|
|
|
|
|
$response = $this->get(route('exercises.index'));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertViewHas('exercises', function ($exercises) {
|
|
|
|
|
return $exercises->total() === 3;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_index_can_filter_by_search_query(): void
|
|
|
|
|
{
|
|
|
|
|
Exercise::factory()->create(['name' => 'Barbell Bench Press']);
|
|
|
|
|
Exercise::factory()->create(['name' => 'Dumbbell Curl']);
|
|
|
|
|
|
|
|
|
|
$response = $this->get(route('exercises.index', ['q' => 'Bench']));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertViewHas('exercises', function ($exercises) {
|
|
|
|
|
return $exercises->total() === 1
|
|
|
|
|
&& $exercises->first()->name === 'Barbell Bench Press';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_index_can_filter_by_body_part(): void
|
|
|
|
|
{
|
|
|
|
|
$chest = BodyPart::create(['name' => 'Chest', 'slug' => 'chest']);
|
|
|
|
|
$back = BodyPart::create(['name' => 'Back', 'slug' => 'back']);
|
|
|
|
|
|
|
|
|
|
$chestExercise = Exercise::factory()->create();
|
|
|
|
|
$chestExercise->bodyParts()->attach($chest->id);
|
|
|
|
|
|
|
|
|
|
$backExercise = Exercise::factory()->create();
|
|
|
|
|
$backExercise->bodyParts()->attach($back->id);
|
|
|
|
|
|
|
|
|
|
$response = $this->get(route('exercises.index', ['bodypart' => 'chest']));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertViewHas('exercises', function ($exercises) use ($chestExercise) {
|
|
|
|
|
return $exercises->total() === 1
|
|
|
|
|
&& $exercises->first()->id === $chestExercise->id;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_show_displays_exercise(): void
|
|
|
|
|
{
|
|
|
|
|
$exercise = Exercise::factory()->create(['name' => 'Barbell Squat']);
|
|
|
|
|
|
|
|
|
|
$response = $this->get(route('exercises.show', $exercise->slug));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertSee('Barbell Squat');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_show_returns_404_for_unknown_slug(): void
|
|
|
|
|
{
|
|
|
|
|
$response = $this->get('/exercises/does-not-exist');
|
|
|
|
|
|
|
|
|
|
$response->assertNotFound();
|
|
|
|
|
}
|
2026-08-10 12:15:14 +03:00
|
|
|
|
|
|
|
|
public function test_show_displays_personal_best_from_completed_session_items(): void
|
|
|
|
|
{
|
|
|
|
|
$user = User::factory()->create();
|
|
|
|
|
$exercise = Exercise::factory()->create();
|
|
|
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
|
|
|
$workoutExercise = WorkoutExercise::factory()->create(['workout_id' => $workout->id, 'exercise_id' => $exercise->id]);
|
|
|
|
|
$session = WorkoutSession::factory()->create(['user_id' => $user->id, 'workout_id' => $workout->id]);
|
|
|
|
|
|
|
|
|
|
WorkoutSessionItem::factory()->create([
|
|
|
|
|
'session_id' => $session->id,
|
|
|
|
|
'workout_exercise_id' => $workoutExercise->id,
|
|
|
|
|
'done' => true,
|
|
|
|
|
'actual_weight' => 60,
|
|
|
|
|
'actual_reps' => 5,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$response = $this->actingAs($user)->get(route('exercises.show', $exercise->slug));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertSee('60 kg', false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_show_picks_the_heaviest_completed_set_across_sessions_as_personal_best(): void
|
|
|
|
|
{
|
|
|
|
|
$user = User::factory()->create();
|
|
|
|
|
$exercise = Exercise::factory()->create();
|
|
|
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
|
|
|
$workoutExercise = WorkoutExercise::factory()->create(['workout_id' => $workout->id, 'exercise_id' => $exercise->id]);
|
|
|
|
|
$earlierSession = WorkoutSession::factory()->create(['user_id' => $user->id, 'workout_id' => $workout->id]);
|
|
|
|
|
$laterSession = WorkoutSession::factory()->create(['user_id' => $user->id, 'workout_id' => $workout->id]);
|
|
|
|
|
|
|
|
|
|
WorkoutSessionItem::factory()->create([
|
|
|
|
|
'session_id' => $earlierSession->id, 'workout_exercise_id' => $workoutExercise->id,
|
|
|
|
|
'done' => true, 'actual_weight' => 60, 'actual_reps' => 5,
|
|
|
|
|
]);
|
|
|
|
|
WorkoutSessionItem::factory()->create([
|
|
|
|
|
'session_id' => $laterSession->id, 'workout_exercise_id' => $workoutExercise->id,
|
|
|
|
|
'done' => true, 'actual_weight' => 70, 'actual_reps' => 3,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$response = $this->actingAs($user)->get(route('exercises.show', $exercise->slug));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertSee('70 kg', false);
|
|
|
|
|
$response->assertDontSee('60 kg', false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_show_ignores_incomplete_sets_for_personal_best(): void
|
|
|
|
|
{
|
|
|
|
|
$user = User::factory()->create();
|
|
|
|
|
$exercise = Exercise::factory()->create();
|
|
|
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
|
|
|
$workoutExercise = WorkoutExercise::factory()->create(['workout_id' => $workout->id, 'exercise_id' => $exercise->id]);
|
|
|
|
|
$session = WorkoutSession::factory()->create(['user_id' => $user->id, 'workout_id' => $workout->id]);
|
|
|
|
|
|
|
|
|
|
WorkoutSessionItem::factory()->create([
|
|
|
|
|
'session_id' => $session->id, 'workout_exercise_id' => $workoutExercise->id,
|
|
|
|
|
'done' => false, 'actual_weight' => 90, 'actual_reps' => 5,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$response = $this->actingAs($user)->get(route('exercises.show', $exercise->slug));
|
|
|
|
|
|
|
|
|
|
$response->assertOk();
|
|
|
|
|
$response->assertDontSee('90 kg', false);
|
|
|
|
|
}
|
2026-08-10 11:47:51 +03:00
|
|
|
}
|