find('app:doctors:repair') ); } /** پزشک irimc با نام عنوان‌دار و درجهٔ جابه‌جا — دقیقاً شکل رکوردهای معیوب. */ private function makeBrokenDoctor(): Doctor { $em = static::getContainer()->get('doctrine')->getManager(); $mobile = '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT); $user = new \App\Auth\Entity\User($mobile); $user->setStatus(0); $em->persist($user); $doctor = new Doctor($user, 'دکتر آزمون ترمیم'); $doctor->setSource('irimc'); $doctor->setOwnerStatus('unclaimed'); $doctor->setInfo('تخصص بیماری‌های داخلی دکترای حرفه‌ای پزشکی'); $doctor->setDegree('expert'); // غلط: باید specialist باشد $em->persist($doctor); $em->flush(); return $doctor; } public function testEveryStepIsAutoDiscovered(): void { self::bootKernel(); try { $steps = iterator_to_array( static::getContainer()->get('test.doctor_repair_steps'), false ); } catch (ServiceNotFoundException) { // بدون alias عمومی برای تگ، از خروجی --list به‌عنوان منبع حقیقت استفاده کن. $tester = $this->tester(); $tester->execute(['--list' => true]); $out = $tester->getDisplay(); foreach (['names', 'degrees', 'specialty-parents', 'surrogate-role'] as $name) { $this->assertStringContainsString($name, $out, "گام «$name» در --list نیست"); } return; } $names = array_map(fn (DoctorRepairStep $s) => $s->name(), $steps); foreach (['names', 'degrees', 'specialty-parents', 'surrogate-role'] as $name) { $this->assertContains($name, $names); } } public function testDryRunWritesNothing(): void { $doctor = $this->makeBrokenDoctor(); $em = static::getContainer()->get('doctrine')->getManager(); $id = $doctor->getId(); $tester = $this->tester(); $tester->execute(['--dry-run' => true, '--only' => 'degrees,names']); $tester->assertCommandIsSuccessful(); $em->clear(); $fresh = $em->getRepository(Doctor::class)->find($id); $this->assertSame('expert', $fresh->getDegree(), 'dry-run نباید درجه را عوض کند'); $this->assertSame('دکتر آزمون ترمیم', $fresh->getName(), 'dry-run نباید نام را عوض کند'); } public function testRepairFixesDegreeAndNameThenIsIdempotent(): void { $doctor = $this->makeBrokenDoctor(); $em = static::getContainer()->get('doctrine')->getManager(); $id = $doctor->getId(); $this->tester()->execute(['--only' => 'degrees,names']); $em->clear(); $fresh = $em->getRepository(Doctor::class)->find($id); $this->assertSame('specialist', $fresh->getDegree(), 'درجه باید از عنوان خام بازمحاسبه شود'); $this->assertSame('آزمون ترمیم', $fresh->getName(), 'پیشوند «دکتر» باید حذف شود'); // اجرای دوم: همان رکورد دیگر نباید در خروجی بیاید. $second = $this->tester(); $second->execute(['--only' => 'degrees,names']); $this->assertStringNotContainsString("#$id ", $second->getDisplay(), 'گام باید idempotent باشد'); } public function testUnknownStepIsRejected(): void { $tester = $this->tester(); $tester->execute(['--only' => 'nonsense']); $this->assertSame(2, $tester->getStatusCode(), 'گام ناشناخته باید INVALID برگرداند'); $this->assertStringContainsString('گام ناشناخته', $tester->getDisplay()); } }