feat: implement filtered and paginated doctor appointments panel with status filtering
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Appointment;
|
||||
|
||||
use App\Appointment\Entity\Appointment;
|
||||
use App\Appointment\Repository\AppointmentRepository;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* Filtered + paginated doctor appointment list backing the dashboard filter bar
|
||||
* (AppointmentRepository::searchByDoctor).
|
||||
*/
|
||||
class DoctorAppointmentFilterTest extends ApiTestCase
|
||||
{
|
||||
private function repo(): AppointmentRepository
|
||||
{
|
||||
return $this->em->getRepository(Appointment::class);
|
||||
}
|
||||
|
||||
private function makeDoctor(): Doctor
|
||||
{
|
||||
$doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'دکتر تست');
|
||||
$this->em->persist($doctor);
|
||||
$this->em->flush();
|
||||
|
||||
return $doctor;
|
||||
}
|
||||
|
||||
private function booking(Doctor $doctor, int $start, ?string $status = null, ?string $name = null): Appointment
|
||||
{
|
||||
$a = new Appointment($doctor, $this->createUser(), $start, $start + 1_800);
|
||||
if ($name !== null) {
|
||||
$a->setPatientName($name);
|
||||
}
|
||||
if ($status === Appointment::STATUS_COMPLETED) {
|
||||
$a->transitionTo(Appointment::STATUS_CONFIRMED);
|
||||
$a->transitionTo(Appointment::STATUS_COMPLETED);
|
||||
} elseif ($status !== null) {
|
||||
$a->transitionTo($status);
|
||||
}
|
||||
$this->em->persist($a);
|
||||
$this->em->flush();
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
public function testStatusFilterExcludesVisited(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$base = time() + 86_400;
|
||||
$this->booking($doctor, $base); // pending
|
||||
$this->booking($doctor, $base + 3_600, Appointment::STATUS_CONFIRMED);
|
||||
$this->booking($doctor, $base + 7_200, Appointment::STATUS_COMPLETED);
|
||||
|
||||
$res = $this->repo()->searchByDoctor(
|
||||
$doctor,
|
||||
[Appointment::STATUS_PENDING, Appointment::STATUS_CONFIRMED],
|
||||
);
|
||||
|
||||
self::assertSame(2, $res['total']);
|
||||
foreach ($res['items'] as $a) {
|
||||
self::assertNotSame(Appointment::STATUS_COMPLETED, $a->getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
public function testDateRangeAndNameSearch(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$base = time() + 86_400;
|
||||
$this->booking($doctor, $base, null, 'علی رضایی');
|
||||
$this->booking($doctor, $base + 200_000, null, 'مریم کاظمی');
|
||||
|
||||
$inRange = $this->repo()->searchByDoctor($doctor, [], null, $base - 60, $base + 60);
|
||||
self::assertSame(1, $inRange['total']);
|
||||
self::assertSame('علی رضایی', $inRange['items'][0]->getPatientName());
|
||||
|
||||
$byName = $this->repo()->searchByDoctor($doctor, [], null, null, null, 'کاظمی');
|
||||
self::assertSame(1, $byName['total']);
|
||||
self::assertSame('مریم کاظمی', $byName['items'][0]->getPatientName());
|
||||
}
|
||||
|
||||
public function testPaginationSlicesAndReportsFullTotal(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$base = time() + 86_400;
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$this->booking($doctor, $base + $i * 3_600);
|
||||
}
|
||||
|
||||
$page2 = $this->repo()->searchByDoctor($doctor, [], null, null, null, null, null, 2, 2);
|
||||
|
||||
self::assertSame(5, $page2['total'], 'total باید کل نتایج باشد نه اندازهٔ صفحه');
|
||||
self::assertCount(2, $page2['items']);
|
||||
}
|
||||
|
||||
public function testEmptyResultForUnmatchedFilter(): void
|
||||
{
|
||||
$doctor = $this->makeDoctor();
|
||||
$this->booking($doctor, time() + 86_400);
|
||||
|
||||
$res = $this->repo()->searchByDoctor($doctor, [Appointment::STATUS_NO_SHOW]);
|
||||
|
||||
self::assertSame(0, $res['total']);
|
||||
self::assertSame([], $res['items']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user