feat(validation): enforce naming rules for doctors and clinics to prevent placeholders
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Doctor;
|
||||
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\ClinicInvitation\Entity\ClinicDoctorInvitation;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Shared\Exception\AppException;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* A doctor/clinic name reaches the public site's <title> and search results, so a
|
||||
* phone number or "test" must never be storable. The guard lives on the entity
|
||||
* because eight different call sites construct a Doctor.
|
||||
*/
|
||||
class PollutedNameRejectionTest extends ApiTestCase
|
||||
{
|
||||
public function testDoctorCannotBeCreatedWithPhoneNumberAsName(): void
|
||||
{
|
||||
$this->expectException(AppException::class);
|
||||
new Doctor($this->createUser(['ROLE_DOCTOR']), '09390039833');
|
||||
}
|
||||
|
||||
public function testDoctorCannotBeRenamedToPlaceholder(): void
|
||||
{
|
||||
$doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'دکتر علی احمدی');
|
||||
|
||||
$this->expectException(AppException::class);
|
||||
$doctor->setName('test');
|
||||
}
|
||||
|
||||
public function testClinicCannotBeNamedAfterPhoneNumber(): void
|
||||
{
|
||||
$clinic = new Clinic($this->createUser(['ROLE_CLINIC']));
|
||||
|
||||
$this->expectException(AppException::class);
|
||||
$clinic->setName('09398631203');
|
||||
}
|
||||
|
||||
public function testClinicNameMayStayNullBeforeItIsSet(): void
|
||||
{
|
||||
$clinic = new Clinic($this->createUser(['ROLE_CLINIC']));
|
||||
$clinic->setName(null);
|
||||
|
||||
$this->assertNull($clinic->getName());
|
||||
}
|
||||
|
||||
public function testAdminCreatingDoctorWithPhoneNameGets422(): void
|
||||
{
|
||||
$admin = $this->createUser(['ROLE_ADMIN']);
|
||||
$this->em->flush();
|
||||
|
||||
$this->authJson('POST', '/api/v1/admin/doctors', $admin, [
|
||||
'name' => '09390039833',
|
||||
'mobile_number' => '0912' . random_int(1000000, 9999999),
|
||||
]);
|
||||
|
||||
$this->assertSame(422, $this->responseCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* ریشهٔ آلودگی تولیدی: دعوت پزشک فقط با موبایل، شماره را بهعنوان نام مینشاند.
|
||||
*/
|
||||
public function testInvitingDoctorByMobileDoesNotUseMobileAsName(): void
|
||||
{
|
||||
$owner = $this->createUser(['ROLE_CLINIC']);
|
||||
$clinic = new Clinic($owner);
|
||||
$this->em->persist($clinic);
|
||||
$this->em->flush();
|
||||
|
||||
$mobile = '0912' . random_int(1000000, 9999999);
|
||||
$this->authJson('POST', "/api/v1/admin/clinic/{$clinic->getUuid()}/invite-doctor", $owner, [
|
||||
'mobile' => $mobile,
|
||||
]);
|
||||
$this->assertSame(201, $this->responseCode());
|
||||
|
||||
$invitation = $this->em->getRepository(ClinicDoctorInvitation::class)
|
||||
->findOneBy(['mobile' => $mobile]);
|
||||
$this->assertNotNull($invitation, 'invitation was not created');
|
||||
|
||||
$this->client->request('POST', "/api/v1/clinic-invitation/{$invitation->getToken()}/accept");
|
||||
$this->assertSame(200, $this->responseCode());
|
||||
|
||||
$this->em->clear();
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['mobileNumber' => $mobile]);
|
||||
|
||||
$this->assertNotNull($doctor, 'invited doctor was not created');
|
||||
$this->assertNotSame($mobile, $doctor->getName(), 'mobile number leaked into the doctor name');
|
||||
$this->assertSame('پزشک دعوتشده', $doctor->getName());
|
||||
}
|
||||
|
||||
public function testInvitedNameIsUsedWhenTheClinicProvidesOne(): void
|
||||
{
|
||||
$owner = $this->createUser(['ROLE_CLINIC']);
|
||||
$clinic = new Clinic($owner);
|
||||
$this->em->persist($clinic);
|
||||
$this->em->flush();
|
||||
|
||||
$mobile = '0912' . random_int(1000000, 9999999);
|
||||
$this->authJson('POST', "/api/v1/admin/clinic/{$clinic->getUuid()}/invite-doctor", $owner, [
|
||||
'mobile' => $mobile,
|
||||
'name' => 'دکتر مریم رضایی',
|
||||
]);
|
||||
$this->assertSame(201, $this->responseCode());
|
||||
|
||||
$invitation = $this->em->getRepository(ClinicDoctorInvitation::class)
|
||||
->findOneBy(['mobile' => $mobile]);
|
||||
$this->client->request('POST', "/api/v1/clinic-invitation/{$invitation->getToken()}/accept");
|
||||
$this->assertSame(200, $this->responseCode());
|
||||
|
||||
$this->em->clear();
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['mobileNumber' => $mobile]);
|
||||
$this->assertSame('دکتر مریم رضایی', $doctor->getName());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user