127 lines
4.7 KiB
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 نباید با پیشفرض حذف شود');
|
|
}
|
|
}
|