Files
clinicpro/tests/Patient/PatientAttachmentTest.php
hamedandClaude Opus 4.8 537bb8c7b3 feat(patients): phase B2 — attachments (ضمیمه)
Add patient file attachments: a new PatientAttachment entity (record-scoped,
CASCADE) + repository, and endpoints GET /patient/{uuid}/attachments,
POST /patient/{uuid}/attachment (raw-body upload) and DELETE
/patient/attachment/{uuid} (owner-scoped). Factor the shared raw-body upload
logic into FileUploadService. Wire the "ضمیمه" tab in PatientDetailPage
(upload + list + delete). PHPUnit covers list/delete/ownership; Vitest covers
the tab. API docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 15:20:00 +03:30

63 lines
2.2 KiB
PHP

<?php
namespace App\Tests\Patient;
use App\Doctor\Entity\Doctor;
use App\Patient\Entity\PatientAttachment;
use App\Patient\Entity\PatientRecord;
use App\Tests\ApiTestCase;
/**
* Patient attachments: list, delete, and tenant ownership scoping.
*/
class PatientAttachmentTest extends ApiTestCase
{
/** @return array{0: \App\Auth\Entity\User, 1: PatientRecord} */
private function recordFor(): array
{
$owner = $this->createUser(['ROLE_DOCTOR']);
$doctor = new Doctor($owner, 'دکتر');
$this->em->persist($doctor);
$this->em->flush();
$patient = $this->createUser(['ROLE_USER']);
$record = new PatientRecord('doctor', $doctor->getId(), $patient, 'doctor', $doctor->getId());
$this->em->persist($record);
$this->em->flush();
return [$owner, $record];
}
public function testListAndDelete(): void
{
[$owner, $record] = $this->recordFor();
$att = new PatientAttachment($record, 'آزمایش.pdf', '/uploads/patients/attachments/x.pdf', 'application/pdf', 1234);
$this->em->persist($att);
$this->em->flush();
$attUuid = $att->getUuid();
$list = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/attachments', $owner);
self::assertSame(200, $this->responseCode());
self::assertCount(1, $list['data']);
self::assertSame('آزمایش.pdf', $list['data'][0]['name']);
$this->authJson('DELETE', '/api/v1/patient/attachment/' . $attUuid, $owner);
self::assertSame(200, $this->responseCode());
$after = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/attachments', $owner);
self::assertCount(0, $after['data']);
}
public function testCannotDeleteAnotherTenantsAttachment(): void
{
[, $record] = $this->recordFor();
$att = new PatientAttachment($record, 'x.pdf', '/uploads/x.pdf');
$this->em->persist($att);
$this->em->flush();
[$otherOwner] = $this->recordFor();
$this->authJson('DELETE', '/api/v1/patient/attachment/' . $att->getUuid(), $otherOwner);
self::assertSame(404, $this->responseCode());
}
}