branches->pair($user)` را صدا می‌زد ولی `AddressResolver` هرگز تزریق * نشده بود، پس هر درخواستِ دارای `treatment_session_uuid` روی «Undefined * property» ۵۰۰ می‌گرفت. phpstan همان را گزارش می‌کرد، اما بین ۱۶ خطای بی‌اثر * دیگر گم شده بود. */ class AppointmentTreatmentSessionLinkTest extends ApiTestCase { /** * این تست چند درخواستِ کرنل پشت‌سرهم می‌زند و هر کدام `$this->em` را کهنه * می‌کند. بدون ریست، همان نمونه به تست بعدی ارث می‌رسد و آنجا — نه اینجا — * با «Multiple non-persisted new entities» می‌شکند. همان دامی که * ApiLeastPrivilegeTest قبلاً برایش همین tearDown را گذاشت. */ protected function tearDown(): void { static::getContainer()->get('doctrine')->resetManager(); parent::tearDown(); } /** @return array{0: User, 1: Doctor} */ private function doctor(): array { $owner = $this->createUser(['ROLE_DOCTOR']); $doctor = new Doctor($owner, 'دکتر تست'); $this->em->persist($doctor); $this->em->flush(); return [$owner, $doctor]; } private function body(string $doctorUuid, array $extra = []): array { $start = time() + 86_400 + random_int(0, 3_600) * 100; return $extra + [ 'doctor_uuid' => $doctorUuid, 'slot_start' => $start, 'slot_end' => $start + 1_800, 'patient_mobile' => '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT), 'patient_name' => 'بیمار تست', 'patient_national_code' => '00' . str_pad((string) random_int(0, 99_999_999), 8, '0', STR_PAD_LEFT), ]; } /** موفق: مسیر عادی بدون اتصال، دست‌نخورده. */ public function testBookingWithoutSessionLinkStillWorks(): void { [$owner, $doctor] = $this->doctor(); $this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body($doctor->getUuid())); self::assertSame(201, $this->responseCode()); } /** * خطا: uuidِ ناموجود باید ۴۰۴ـی بگیرد که از `SessionBookingLink` می‌آید. * * ۵۰۰ گرفتن یعنی اجرا اصلاً به آن سرویس نرسیده — همان رگرسیونی که این تست * برایش نوشته شده. */ public function testBookingWithUnknownSessionUuidIsRejectedNotCrashed(): void { [$owner, $doctor] = $this->doctor(); $body = $this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body( $doctor->getUuid(), ['treatment_session_uuid' => '00000000-0000-0000-0000-000000000000'], )); self::assertSame(404, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE)); self::assertSame('ERR_NOT_FOUND_001', $body['errors'][0]['code']); self::assertSame('treatment_session_uuid', $body['errors'][0]['field'] ?? null); } /** مرزی: رشتهٔ خالی یعنی «اتصالی در کار نیست»، نه uuidِ نامعتبر. */ public function testEmptySessionUuidIsTreatedAsNoLink(): void { [$owner, $doctor] = $this->doctor(); $this->authJson('POST', '/api/v1/my/appointment', $owner, $this->body( $doctor->getUuid(), ['treatment_session_uuid' => ' '], )); self::assertSame(201, $this->responseCode()); } }