Files
clinicpro/tests/UserProfile/TourProgressApiTest.php
T
hamed 20c8eaaad9 feat: add TourProgressController and related entities for user tour progress tracking
- Implemented TourProgressController to handle API endpoints for tracking guided tours seen by users.
- Created UserTourProgress entity to store the highest version of tours seen by each user.
- Developed UserTourProgressRepository for database interactions related to user tour progress.
- Introduced TourProgressService to manage business logic for marking tours as seen and retrieving seen maps.
- Added comprehensive tests for API endpoints and entity behavior to ensure functionality and data integrity.
2026-08-10 09:34:14 +03:30

98 lines
3.4 KiB
PHP

<?php
namespace App\Tests\UserProfile;
use App\Tests\ApiTestCase;
use App\UserProfile\Entity\UserTourProgress;
use PHPUnit\Framework\Attributes\DataProvider;
class TourProgressApiTest extends ApiTestCase
{
public function testSeenListStartsEmptyAndGrowsAfterMarking(): void
{
$user = $this->createUser();
$body = $this->authJson('GET', '/api/v1/my/tours', $user);
self::assertSame(200, $this->responseCode());
self::assertSame([], (array) $body['data']['seen']);
$this->authJson('POST', '/api/v1/my/tours/appointments/seen', $user, ['version' => 2]);
self::assertSame(200, $this->responseCode());
$body = $this->authJson('GET', '/api/v1/my/tours', $user);
self::assertSame(['appointments' => 2], (array) $body['data']['seen']);
}
public function testMarkingTheSameTourAgainUpdatesTheRowInPlace(): void
{
$user = $this->createUser();
$this->authJson('POST', '/api/v1/my/tours/appointments/seen', $user, ['version' => 1]);
$this->authJson('POST', '/api/v1/my/tours/appointments/seen', $user, ['version' => 3]);
self::assertSame(200, $this->responseCode());
$rows = $this->em->getRepository(UserTourProgress::class)->findBy(['user' => $user]);
self::assertCount(1, $rows);
self::assertSame(3, $rows[0]->getVersion());
}
public function testAnOlderVersionNeverLowersTheStoredOne(): void
{
$user = $this->createUser();
$this->authJson('POST', '/api/v1/my/tours/appointments/seen', $user, ['version' => 5]);
$this->authJson('POST', '/api/v1/my/tours/appointments/seen', $user, ['version' => 2]);
$body = $this->authJson('GET', '/api/v1/my/tours', $user);
self::assertSame(['appointments' => 5], (array) $body['data']['seen']);
}
public function testSeenListIsPrivateToTheUser(): void
{
$user = $this->createUser();
$other = $this->createUser();
$this->authJson('POST', '/api/v1/my/tours/appointments/seen', $other, ['version' => 1]);
$body = $this->authJson('GET', '/api/v1/my/tours', $user);
self::assertSame([], (array) $body['data']['seen']);
}
public function testBothEndpointsRequireAuthentication(): void
{
$this->client->request('GET', '/api/v1/my/tours');
self::assertSame(401, $this->responseCode());
$this->client->request('POST', '/api/v1/my/tours/appointments/seen');
self::assertSame(401, $this->responseCode());
}
#[DataProvider('invalidVersions')]
public function testInvalidVersionIsRejected(mixed $version): void
{
$user = $this->createUser();
$body = $this->authJson('POST', '/api/v1/my/tours/appointments/seen', $user, ['version' => $version]);
self::assertSame(422, $this->responseCode());
self::assertSame('version', $body['errors'][0]['field']);
self::assertSame([], $this->em->getRepository(UserTourProgress::class)->findBy(['user' => $user]));
}
public static function invalidVersions(): iterable
{
yield 'zero' => [0];
yield 'string' => ['1'];
yield 'float' => [1.5];
}
public function testAnUnknownTourIdShapeIsNotRouted(): void
{
$user = $this->createUser();
$this->authJson('POST', '/api/v1/my/tours/Appointments%20Page/seen', $user, ['version' => 1]);
self::assertSame(404, $this->responseCode());
}
}