Only Breeze's default auth/profile tests existed - nothing covered Workouts, Sessions, Exercises, Yoga, Favorites, Blog, or the Admin panel, which is the actual product. Adds factories for the domain models and 45 new feature tests covering the main flows plus authorization boundaries (owner-only access on workouts/sessions, admin-only access on /admin, drafts hidden from the public blog). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
150 lines
4.8 KiB
PHP
150 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\Exercise;
|
|
use App\Models\User;
|
|
use App\Models\Workout;
|
|
use App\Models\WorkoutExercise;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
|
|
class WorkoutTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_guest_is_redirected_to_login(): void
|
|
{
|
|
$response = $this->get(route('workouts.index'));
|
|
|
|
$response->assertRedirect(route('login'));
|
|
}
|
|
|
|
public function test_user_can_create_a_workout(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
|
|
$response = $this->actingAs($user)->post(route('workouts.store'), [
|
|
'title' => 'Leg Day',
|
|
'notes' => 'Focus on form',
|
|
'estimated_minutes' => 45,
|
|
]);
|
|
|
|
$this->assertDatabaseHas('workouts', [
|
|
'user_id' => $user->id,
|
|
'title' => 'Leg Day',
|
|
]);
|
|
$workout = Workout::where('title', 'Leg Day')->firstOrFail();
|
|
$response->assertRedirect(route('workouts.show', $workout));
|
|
}
|
|
|
|
public function test_owner_can_view_their_workout(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
|
|
$response = $this->actingAs($user)->get(route('workouts.show', $workout));
|
|
|
|
$response->assertOk();
|
|
$response->assertSee($workout->title);
|
|
}
|
|
|
|
public function test_other_user_cannot_view_workout(): void
|
|
{
|
|
$owner = User::factory()->create();
|
|
$other = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $owner->id]);
|
|
|
|
$response = $this->actingAs($other)->get(route('workouts.show', $workout));
|
|
|
|
$response->assertForbidden();
|
|
}
|
|
|
|
public function test_owner_can_add_exercise_to_workout(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
$exercise = Exercise::factory()->create();
|
|
|
|
$response = $this->actingAs($user)->post(route('workouts.exercises.add', $workout), [
|
|
'exercise_id' => $exercise->id,
|
|
'sets' => 4,
|
|
'reps' => 8,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
$this->assertDatabaseHas('workout_exercises', [
|
|
'workout_id' => $workout->id,
|
|
'exercise_id' => $exercise->id,
|
|
'sets' => 4,
|
|
'reps' => 8,
|
|
]);
|
|
}
|
|
|
|
public function test_other_user_cannot_add_exercise_to_workout(): void
|
|
{
|
|
$owner = User::factory()->create();
|
|
$other = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $owner->id]);
|
|
$exercise = Exercise::factory()->create();
|
|
|
|
$response = $this->actingAs($other)->post(route('workouts.exercises.add', $workout), [
|
|
'exercise_id' => $exercise->id,
|
|
]);
|
|
|
|
$response->assertForbidden();
|
|
}
|
|
|
|
public function test_owner_can_update_workout_exercise(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
$item = WorkoutExercise::factory()->create(['workout_id' => $workout->id, 'sets' => 3]);
|
|
|
|
$response = $this->actingAs($user)->patch(route('workouts.exercises.update', [$workout, $item]), [
|
|
'sets' => 5,
|
|
]);
|
|
|
|
$response->assertRedirect();
|
|
$this->assertDatabaseHas('workout_exercises', [
|
|
'id' => $item->id,
|
|
'sets' => 5,
|
|
]);
|
|
}
|
|
|
|
public function test_owner_can_remove_workout_exercise(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
$item = WorkoutExercise::factory()->create(['workout_id' => $workout->id]);
|
|
|
|
$response = $this->actingAs($user)->delete(route('workouts.exercises.remove', [$workout, $item]));
|
|
|
|
$response->assertRedirect();
|
|
$this->assertDatabaseMissing('workout_exercises', ['id' => $item->id]);
|
|
}
|
|
|
|
public function test_owner_can_delete_workout(): void
|
|
{
|
|
$user = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $user->id]);
|
|
|
|
$response = $this->actingAs($user)->delete(route('workouts.destroy', $workout));
|
|
|
|
$response->assertRedirect(route('workouts.index'));
|
|
$this->assertDatabaseMissing('workouts', ['id' => $workout->id]);
|
|
}
|
|
|
|
public function test_other_user_cannot_delete_workout(): void
|
|
{
|
|
$owner = User::factory()->create();
|
|
$other = User::factory()->create();
|
|
$workout = Workout::factory()->create(['user_id' => $owner->id]);
|
|
|
|
$response = $this->actingAs($other)->delete(route('workouts.destroy', $workout));
|
|
|
|
$response->assertForbidden();
|
|
$this->assertDatabaseHas('workouts', ['id' => $workout->id]);
|
|
}
|
|
}
|