feat: workout sesssions
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\WorkoutSource;
|
||||
use App\Models\User;
|
||||
use App\Models\WorkoutSessions;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('creates a workout for the authenticated user', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$response = $this->postJson('/api/workouts', [
|
||||
'external_id' => 'apple-workout-1',
|
||||
'source' => WorkoutSource::APPLE_HEALTH->value,
|
||||
'type' => 'running',
|
||||
'title' => 'Morning run',
|
||||
'duration_seconds' => 1800,
|
||||
'calories_burned' => 450,
|
||||
'distance_meters' => 5200,
|
||||
'started_at' => '2026-05-19T07:30:00.000Z',
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertCreated()
|
||||
->assertJsonPath('data.externalId', 'apple-workout-1')
|
||||
->assertJsonPath('data.source', WorkoutSource::APPLE_HEALTH->value)
|
||||
->assertJsonPath('data.type', 'running')
|
||||
->assertJsonPath('data.title', 'Morning run')
|
||||
->assertJsonPath('data.durationSeconds', 1800)
|
||||
->assertJsonPath('data.caloriesBurned', 450)
|
||||
->assertJsonPath('data.distanceMeters', 5200);
|
||||
|
||||
$this->assertDatabaseHas('workout_sessions', [
|
||||
'id' => $response->json('data.id'),
|
||||
'user_id' => $user->id,
|
||||
'external_id' => 'apple-workout-1',
|
||||
'source' => WorkoutSource::APPLE_HEALTH->value,
|
||||
'type' => 'running',
|
||||
'title' => 'Morning run',
|
||||
'duration_seconds' => 1800,
|
||||
'calories_burned' => 450,
|
||||
'distance_meters' => 5200,
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns workouts for the authenticated user', function () {
|
||||
$user = User::factory()->create();
|
||||
$otherUser = User::factory()->create();
|
||||
|
||||
$oldWorkoutSession = WorkoutSessions::factory()->for($user, 'user')->create([
|
||||
'external_id' => 'manual-1',
|
||||
'source' => WorkoutSource::MANUAL,
|
||||
'type' => 'strength',
|
||||
'title' => 'Upper body',
|
||||
'duration_seconds' => 2400,
|
||||
'calories_burned' => 320,
|
||||
'distance_meters' => 0,
|
||||
'started_at' => '2026-05-18 10:00:00',
|
||||
]);
|
||||
$latestWorkoutSession = WorkoutSessions::factory()->for($user, 'user')->create([
|
||||
'external_id' => 'apple-1',
|
||||
'source' => WorkoutSource::APPLE_HEALTH,
|
||||
'type' => 'running',
|
||||
'title' => 'Morning run',
|
||||
'duration_seconds' => 1800,
|
||||
'calories_burned' => 450,
|
||||
'distance_meters' => 5200,
|
||||
'started_at' => '2026-05-19 07:30:00',
|
||||
]);
|
||||
$otherWorkoutSession = WorkoutSessions::factory()->for($otherUser, 'user')->create([
|
||||
'title' => 'Hidden workout',
|
||||
'started_at' => '2026-05-20 07:30:00',
|
||||
]);
|
||||
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$response = $this->getJson('/api/workouts');
|
||||
|
||||
$response
|
||||
->assertOk()
|
||||
->assertJsonCount(2, 'data')
|
||||
->assertJsonPath('data.0.id', $latestWorkoutSession->id)
|
||||
->assertJsonPath('data.0.externalId', 'apple-1')
|
||||
->assertJsonPath('data.0.source', WorkoutSource::APPLE_HEALTH->value)
|
||||
->assertJsonPath('data.0.type', 'running')
|
||||
->assertJsonPath('data.0.title', 'Morning run')
|
||||
->assertJsonPath('data.0.durationSeconds', 1800)
|
||||
->assertJsonPath('data.0.caloriesBurned', 450)
|
||||
->assertJsonPath('data.0.distanceMeters', 5200)
|
||||
->assertJsonPath('data.1.id', $oldWorkoutSession->id)
|
||||
->assertJsonMissing([
|
||||
'id' => $otherWorkoutSession->id,
|
||||
]);
|
||||
});
|
||||
|
||||
it('validates the workouts pagination size', function () {
|
||||
Sanctum::actingAs(User::factory()->create());
|
||||
|
||||
$this
|
||||
->getJson('/api/workouts?per_page=101')
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors(['per_page']);
|
||||
});
|
||||
|
||||
it('validates workout creation data', function () {
|
||||
Sanctum::actingAs(User::factory()->create());
|
||||
|
||||
$this
|
||||
->postJson('/api/workouts', [
|
||||
'source' => 'invalid',
|
||||
'type' => '',
|
||||
'title' => '',
|
||||
'duration_seconds' => 0,
|
||||
'calories_burned' => -1,
|
||||
'distance_meters' => -1,
|
||||
'started_at' => 'not-a-date',
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors([
|
||||
'source',
|
||||
'type',
|
||||
'title',
|
||||
'duration_seconds',
|
||||
'calories_burned',
|
||||
'distance_meters',
|
||||
'started_at',
|
||||
]);
|
||||
});
|
||||
|
||||
it('validates workout external ids per source', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
WorkoutSessions::factory()->create([
|
||||
'external_id' => 'manual-1',
|
||||
'source' => WorkoutSource::MANUAL,
|
||||
]);
|
||||
|
||||
Sanctum::actingAs($user);
|
||||
|
||||
$this
|
||||
->postJson('/api/workouts', [
|
||||
'external_id' => 'manual-1',
|
||||
'source' => WorkoutSource::MANUAL->value,
|
||||
'type' => 'running',
|
||||
'title' => 'Morning run',
|
||||
'duration_seconds' => 1800,
|
||||
'calories_burned' => 450,
|
||||
'distance_meters' => 5200,
|
||||
])
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors(['external_id']);
|
||||
});
|
||||
Reference in New Issue
Block a user