- Add NewAppointmentsTable for displaying today's appointments with status chips and formatted time. - Implement TauriCharts for bar and line charts representing patient counts and revenue. - Create TauriDashboardView to combine stat cards, charts, and new appointments list. - Introduce TauriStatCards for displaying key statistics with icons. - Add dashboardIcons for SVG icons used in stat cards. - Implement tests for DashboardPage to ensure correct rendering and API calls. - Create DashboardTodayAppointmentsTest to validate extended fields in today's appointments API response.
131 lines
4.8 KiB
PHP
131 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Dashboard;
|
|
|
|
use App\Appointment\Entity\Appointment;
|
|
use App\Auth\Entity\User;
|
|
use App\Clinic\Entity\Clinic;
|
|
use App\ClinicService\Entity\ServiceItem;
|
|
use App\ClinicService\Entity\ServiceSection;
|
|
use App\Doctor\Entity\Doctor;
|
|
use App\Tests\ApiTestCase;
|
|
|
|
/**
|
|
* GET /api/v1/dashboard/{doctor,clinic} — `today_appointments` rows must carry
|
|
* the extended fields (patient_mobile, doctor_name, service_name, slot_end)
|
|
* added for the ported «لیست نوبتهای جدید» dashboard table.
|
|
*
|
|
* NOTE: db_test is never reset, so patient mobiles use the ApiTestCase random
|
|
* generator (never hardcoded) to avoid unique-constraint clashes across runs.
|
|
*/
|
|
class DashboardTodayAppointmentsTest extends ApiTestCase
|
|
{
|
|
private function todayAppointment(Doctor $doctor, User $patient): Appointment
|
|
{
|
|
// now() is guaranteed within [today midnight, tomorrow midnight-1]
|
|
$start = time();
|
|
$appt = new Appointment($doctor, $patient, $start, $start + 1_800);
|
|
$this->em->persist($appt);
|
|
$this->em->flush();
|
|
|
|
return $appt;
|
|
}
|
|
|
|
public function testDoctorTodayAppointmentsExposeExtendedFields(): void
|
|
{
|
|
$owner = $this->createUser(['ROLE_DOCTOR']);
|
|
$doctor = new Doctor($owner, 'حمیدی');
|
|
$patient = $this->createUser(['ROLE_USER']);
|
|
|
|
$section = new ServiceSection('doctor', 1, 'عمومی');
|
|
$item = new ServiceItem($section, 'ویزیت عمومی');
|
|
$this->em->persist($doctor);
|
|
$this->em->persist($section);
|
|
$this->em->persist($item);
|
|
$this->em->flush();
|
|
|
|
$appt = $this->todayAppointment($doctor, $patient);
|
|
$appt->setServiceItem($item);
|
|
$this->em->flush();
|
|
|
|
$res = $this->authJson('GET', '/api/v1/dashboard/doctor', $owner);
|
|
self::assertSame(200, $this->responseCode());
|
|
|
|
$rows = $res['data']['today_appointments'];
|
|
self::assertNotEmpty($rows, 'today_appointments should contain the booked slot');
|
|
$row = $rows[0];
|
|
|
|
self::assertSame($patient->getMobileNumber(), $row['patient_mobile']);
|
|
self::assertSame('حمیدی', $row['doctor_name']);
|
|
self::assertSame('ویزیت عمومی', $row['service_name']);
|
|
self::assertSame($appt->getSlotStart(), $row['slot_start']);
|
|
self::assertSame($appt->getSlotEnd(), $row['slot_end']);
|
|
self::assertArrayHasKey('status', $row);
|
|
}
|
|
|
|
public function testServiceNameNullWhenNoServiceItem(): void
|
|
{
|
|
$owner = $this->createUser(['ROLE_DOCTOR']);
|
|
$doctor = new Doctor($owner, 'حمیدی');
|
|
$this->em->persist($doctor);
|
|
$this->em->flush();
|
|
|
|
$patient = $this->createUser(['ROLE_USER']);
|
|
$this->todayAppointment($doctor, $patient);
|
|
|
|
$res = $this->authJson('GET', '/api/v1/dashboard/doctor', $owner);
|
|
self::assertSame(200, $this->responseCode());
|
|
$row = $res['data']['today_appointments'][0];
|
|
|
|
self::assertNull($row['service_name'], 'service_name is null when no service item is booked');
|
|
self::assertSame($patient->getMobileNumber(), $row['patient_mobile']);
|
|
}
|
|
|
|
public function testClinicTodayAppointmentsExposeExtendedFields(): void
|
|
{
|
|
$clinicOwner = $this->createUser(['ROLE_CLINIC']);
|
|
$clinic = new Clinic($clinicOwner);
|
|
$clinic->setName('کلینیک نمونه');
|
|
|
|
$docOwner = $this->createUser(['ROLE_DOCTOR']);
|
|
$doctor = new Doctor($docOwner, 'حمیدی');
|
|
$clinic->getDoctors()->add($doctor);
|
|
|
|
$section = new ServiceSection('doctor', 1, 'عمومی');
|
|
$item = new ServiceItem($section, 'ویزیت عمومی');
|
|
$patient = $this->createUser(['ROLE_USER']);
|
|
|
|
$this->em->persist($doctor);
|
|
$this->em->persist($clinic);
|
|
$this->em->persist($section);
|
|
$this->em->persist($item);
|
|
$this->em->flush();
|
|
|
|
$appt = $this->todayAppointment($doctor, $patient);
|
|
$appt->setServiceItem($item);
|
|
$this->em->flush();
|
|
|
|
$res = $this->authJson('GET', '/api/v1/dashboard/clinic', $clinicOwner);
|
|
self::assertSame(200, $this->responseCode());
|
|
|
|
$rows = $res['data']['today_appointments'];
|
|
self::assertNotEmpty($rows);
|
|
$row = $rows[0];
|
|
|
|
self::assertSame($patient->getMobileNumber(), $row['patient_mobile']);
|
|
self::assertSame('حمیدی', $row['doctor_name']);
|
|
self::assertSame('ویزیت عمومی', $row['service_name']);
|
|
self::assertSame($appt->getSlotEnd(), $row['slot_end']);
|
|
}
|
|
|
|
public function testDoctorNotFoundReturns404(): void
|
|
{
|
|
// ROLE_DOCTOR user without a Doctor entity
|
|
$user = $this->createUser(['ROLE_DOCTOR']);
|
|
|
|
$res = $this->authJson('GET', '/api/v1/dashboard/doctor', $user);
|
|
self::assertSame(404, $this->responseCode());
|
|
self::assertFalse($res['success']);
|
|
}
|
|
}
|