Files
clinicpro/tests/Doctor/PurgeUnclaimedDoctorsCommandTest.php

127 lines
4.7 KiB
PHP

<?php
namespace App\Tests\Doctor;
use App\Auth\Entity\User;
use App\Doctor\Command\PurgeUnclaimedDoctorsCommand;
use App\Doctor\Entity\Doctor;
use Doctrine\DBAL\Connection;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;
/**
* `app:doctors:purge-unclaimed` فقط باید پزشکانِ ایمپورت‌شدهٔ claim‌نشده و کاربران
* جانشینشان را حذف کند. این تست دو قرارداد بحرانی را قفل می‌کند: --dry-run هیچ‌چیز
* نمی‌نویسد، و پزشکان claimed / با منبع دیگر هرگز پاک نمی‌شوند.
*/
class PurgeUnclaimedDoctorsCommandTest extends KernelTestCase
{
private function tester(): CommandTester
{
return new CommandTester(
(new Application(self::bootKernel()))->find('app:doctors:purge-unclaimed')
);
}
private function makeDoctor(string $source, string $ownerStatus, int $userStatus = 0): Doctor
{
$em = static::getContainer()->get('doctrine')->getManager();
$mobile = ($userStatus === 0 ? 'imp_' : '09') . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT);
$user = new User($mobile);
$user->setStatus($userStatus);
$em->persist($user);
$doctor = new Doctor($user, 'دکتر آزمون');
$doctor->setSource($source);
$doctor->setOwnerStatus($ownerStatus);
$em->persist($doctor);
$em->flush();
return $doctor;
}
private function doctorExists(int $id): bool
{
$conn = static::getContainer()->get(Connection::class);
return (bool) $conn->fetchOne('SELECT COUNT(*) FROM doctors WHERE id = ?', [$id]);
}
public function testDryRunDeletesNothing(): void
{
$doctor = $this->makeDoctor('irimc', 'unclaimed');
$id = $doctor->getId();
$tester = $this->tester();
$tester->execute([]);
$tester->assertCommandIsSuccessful();
$this->assertTrue($this->doctorExists($id), 'dry-run نباید پزشک را حذف کند');
}
public function testForceDeletesUnclaimedImportedDoctorAndSurrogate(): void
{
$doctor = $this->makeDoctor('irimc', 'unclaimed');
$id = $doctor->getId();
$surrogateId = $doctor->getUser()->getId();
$tester = $this->tester();
$tester->execute(['--force' => true]);
$tester->assertCommandIsSuccessful();
$conn = static::getContainer()->get(Connection::class);
$this->assertFalse($this->doctorExists($id), 'پزشک claim‌نشده باید حذف شود');
$this->assertFalse(
(bool) $conn->fetchOne('SELECT COUNT(*) FROM users WHERE id = ?', [$surrogateId]),
'کاربر جانشین یتیم باید حذف شود',
);
}
/** برخلاف app:doctors:purge، این کامند روی prod قابل اجراست — ولی فقط با سوییچ صریح. */
private function prodTester(): CommandTester
{
self::bootKernel();
return new CommandTester(
new PurgeUnclaimedDoctorsCommand(static::getContainer()->get(Connection::class), 'prod')
);
}
public function testRefusesOnProdWithoutExplicitSwitch(): void
{
$doctor = $this->makeDoctor('irimc', 'unclaimed');
$tester = $this->prodTester();
$tester->execute(['--force' => true]);
$this->assertSame(Command::FAILURE, $tester->getStatusCode());
$this->assertStringContainsString('i-know-this-is-prod', $tester->getDisplay());
$this->assertTrue($this->doctorExists($doctor->getId()), 'گاردِ prod نباید چیزی حذف کند');
}
public function testRunsOnProdWithExplicitSwitch(): void
{
$doctor = $this->makeDoctor('irimc', 'unclaimed');
$tester = $this->prodTester();
$tester->execute(['--force' => true, '--i-know-this-is-prod' => true]);
$tester->assertCommandIsSuccessful();
$this->assertFalse($this->doctorExists($doctor->getId()), 'با سوییچ صریح باید روی prod حذف کند');
}
public function testClaimedAndOtherSourceDoctorsSurvive(): void
{
$claimed = $this->makeDoctor('irimc', 'claimed', userStatus: 1);
$manual = $this->makeDoctor('manual', 'unclaimed');
$this->tester()->execute(['--force' => true]);
$this->assertTrue($this->doctorExists($claimed->getId()), 'پزشک claimed نباید حذف شود');
$this->assertTrue($this->doctorExists($manual->getId()), 'منبع غیر irimc نباید با پیش‌فرض حذف شود');
}
}