createUser(['ROLE_DOCTOR']); $owner->setRealName('دکتر احمدی'); $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 testCreateCapturesAuthorAndDefaults(): void { [$owner, $record] = $this->recordFor(); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, [ 'body' => 'بیمار به دارو حساسیت دارد', ]); self::assertSame(201, $this->responseCode()); self::assertSame('بیمار به دارو حساسیت دارد', $created['data']['body']); self::assertFalse($created['data']['pinned']); self::assertSame('دکتر احمدی', $created['data']['author']); self::assertNull($created['data']['updated_at']); } public function testListReturnsPinnedFirst(): void { [$owner, $record] = $this->recordFor(); $base = '/api/v1/patient/' . $record->getUuid(); // Three notes; the oldest is pinned so it must float above the two newer ones. $pinned = $this->authJson('POST', $base . '/note', $owner, ['body' => 'قدیمی پین‌شده', 'pinned' => true]); $this->authJson('POST', $base . '/note', $owner, ['body' => 'دوم']); $this->authJson('POST', $base . '/note', $owner, ['body' => 'سوم (جدیدترین)']); $list = $this->authJson('GET', $base . '/notes', $owner); self::assertCount(3, $list['data']); self::assertSame($pinned['data']['uuid'], $list['data'][0]['uuid']); self::assertTrue($list['data'][0]['pinned']); // remaining two are newest-first among the unpinned self::assertSame('سوم (جدیدترین)', $list['data'][1]['body']); self::assertSame('دوم', $list['data'][2]['body']); } public function testEditBodyAndTogglePin(): void { [$owner, $record] = $this->recordFor(); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'اولیه']); $uuid = $created['data']['uuid']; $edited = $this->authJson('PATCH', '/api/v1/patient/note/' . $uuid, $owner, [ 'body' => 'ویرایش شد', 'pinned' => true, ]); self::assertSame(200, $this->responseCode()); self::assertSame('ویرایش شد', $edited['data']['body']); self::assertTrue($edited['data']['pinned']); self::assertNotNull($edited['data']['updated_at']); // pin-only toggle keeps body intact $unpinned = $this->authJson('PATCH', '/api/v1/patient/note/' . $uuid, $owner, ['pinned' => false]); self::assertFalse($unpinned['data']['pinned']); self::assertSame('ویرایش شد', $unpinned['data']['body']); } public function testDelete(): void { [$owner, $record] = $this->recordFor(); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'برای حذف']); $uuid = $created['data']['uuid']; $this->authJson('DELETE', '/api/v1/patient/note/' . $uuid, $owner); self::assertSame(200, $this->responseCode()); $after = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/notes', $owner); self::assertCount(0, $after['data']); } public function testRequiresBodyOnCreate(): void { [$owner, $record] = $this->recordFor(); $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => ' ']); self::assertSame(422, $this->responseCode()); } public function testRejectsEmptyBodyOnEdit(): void { [$owner, $record] = $this->recordFor(); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'اولیه']); $this->authJson('PATCH', '/api/v1/patient/note/' . $created['data']['uuid'], $owner, ['body' => '']); self::assertSame(422, $this->responseCode()); } public function testOwnershipScoped(): void { [$owner, $record] = $this->recordFor(); $created = $this->authJson('POST', '/api/v1/patient/' . $record->getUuid() . '/note', $owner, ['body' => 'x']); $uuid = $created['data']['uuid']; [$other] = $this->recordFor(); $this->authJson('PATCH', '/api/v1/patient/note/' . $uuid, $other, ['pinned' => true]); self::assertSame(404, $this->responseCode()); $this->authJson('DELETE', '/api/v1/patient/note/' . $uuid, $other); self::assertSame(404, $this->responseCode()); } }