createUser(['ROLE_USER', 'ROLE_REPRESENTATION']); $this->em->persist(new Representation($user, 'نمایندهٔ ' . uniqid())); $this->em->flush(); return $user; } private function doctorCreatedBy(User $repUser): string { $body = $this->authJson('POST', '/api/v1/representation/doctor', $repUser, [ 'mobile' => '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT), 'name' => 'دکتر فلگ ' . uniqid(), ]); self::assertSame(201, $this->responseCode()); return $body['data']['uuid']; } private function clinicCreatedBy(User $repUser): string { $body = $this->authJson('POST', '/api/v1/representation/clinic', $repUser, [ 'owner_mobile' => '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT), 'name' => 'کلینیک فلگ ' . uniqid(), ]); self::assertSame(200, $this->responseCode()); return $body['data']['uuid']; } /** GET بدون هیچ توکنی. */ private function anonymousGet(string $uri): array { $this->client->request('GET', $uri); return json_decode($this->client->getResponse()->getContent(), true) ?? []; } /** پاسخ جزئیات دولایه است: کنترلر `success(['data' => …])` می‌دهد. */ private function payload(array $body): array { return $body['data']['data']; } private function canEdit(array $body): bool { self::assertArrayHasKey('can_edit', $this->payload($body), 'پاسخ باید همیشه can_edit داشته باشد'); return $this->payload($body)['can_edit']; } // ── پزشک ────────────────────────────────────────────────────────────────── public function testDoctorFlagIsTrueForTheOwningRepresentativeOnly(): void { $owner = $this->newRepresentative(); $stranger = $this->newRepresentative(); $uuid = $this->doctorCreatedBy($owner); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/doctor/' . $uuid, $owner))); self::assertFalse($this->canEdit($this->authJson('GET', '/api/v1/doctor/' . $uuid, $stranger))); } public function testDoctorFlagIsFalseWithoutAToken(): void { $owner = $this->newRepresentative(); $uuid = $this->doctorCreatedBy($owner); $body = $this->anonymousGet('/api/v1/doctor/' . $uuid); self::assertSame(200, $this->client->getResponse()->getStatusCode()); self::assertFalse($this->canEdit($body)); // بقیهٔ پاسخ نباید عوض شده باشد — سایت عمومی همین را مصرف می‌کند. self::assertArrayHasKey('uuid', $this->payload($body)); self::assertArrayHasKey('clinics', $this->payload($body)); } public function testDoctorFlagIsTrueForTheDoctorAndForAnAdmin(): void { $doctorUser = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']); $doctor = new Doctor($doctorUser, 'پزشک فلگ'); $this->em->persist($doctor); $this->em->flush(); $uuid = $doctor->getUuid(); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/doctor/' . $uuid, $doctorUser))); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/doctor/' . $uuid, $this->createUser(['ROLE_ADMIN'])))); self::assertFalse($this->canEdit($this->authJson('GET', '/api/v1/doctor/' . $uuid, $this->createUser(['ROLE_USER'])))); } // ── کلینیک ──────────────────────────────────────────────────────────────── public function testClinicFlagIsTrueForTheOwningRepresentativeOnly(): void { $owner = $this->newRepresentative(); $stranger = $this->newRepresentative(); $uuid = $this->clinicCreatedBy($owner); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/clinic/' . $uuid, $owner))); self::assertFalse($this->canEdit($this->authJson('GET', '/api/v1/clinic/' . $uuid, $stranger))); } public function testClinicFlagIsFalseWithoutAToken(): void { $owner = $this->newRepresentative(); $uuid = $this->clinicCreatedBy($owner); $body = $this->anonymousGet('/api/v1/clinic/' . $uuid); self::assertSame(200, $this->client->getResponse()->getStatusCode()); self::assertFalse($this->canEdit($body)); self::assertArrayHasKey('uuid', $this->payload($body)); } public function testClinicFlagIsTrueForTheOwnerAndForAnAdmin(): void { $ownerUser = $this->createUser(['ROLE_USER', 'ROLE_CLINIC']); $clinic = new Clinic($ownerUser); $clinic->setName('کلینیک فلگ'); $this->em->persist($clinic); $this->em->flush(); $uuid = $clinic->getUuid(); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/clinic/' . $uuid, $ownerUser))); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/clinic/' . $uuid, $this->createUser(['ROLE_ADMIN'])))); self::assertFalse($this->canEdit($this->authJson('GET', '/api/v1/clinic/' . $uuid, $this->createUser(['ROLE_USER'])))); } // ── مرزی ────────────────────────────────────────────────────────────────── public function testFlagMatchesWhatThePatchActuallyAllows(): void { // اگر فلگ true بدهد ولی PATCH ۴۰۳ کند، پنل دکمهٔ مرده نشان می‌دهد. $owner = $this->newRepresentative(); $uuid = $this->doctorCreatedBy($owner); self::assertTrue($this->canEdit($this->authJson('GET', '/api/v1/doctor/' . $uuid, $owner))); $this->authJson('PATCH', '/api/v1/doctor/' . $uuid, $owner, ['info' => 'x']); self::assertSame(200, $this->responseCode()); } }