createUser(['ROLE_USER', 'ROLE_CLINIC']); $clinic = new Clinic($user); $clinic->setName('کلینیک دسته‌بندی'); $this->em->persist($clinic); $this->em->flush(); $address = DoctorAddress::forClinic($clinic->getId()); $address->setName('شعبهٔ مرکزی'); $this->em->persist($address); $this->em->flush(); return [$user, $clinic, $address]; } private function category(User $user, string $name): string { $body = $this->authJson('POST', '/api/v1/service-category', $user, ['name' => $name]); self::assertSame(201, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE)); return $body['data']['uuid']; } // ── ✅ موفق ────────────────────────────────────────────────────────────── public function testACategoryCanIncludeAnother(): void { [$user] = $this->clinic(); $whole = $this->category($user, 'تمام بدن'); $hand = $this->category($user, 'دست'); $this->authJson('POST', "/api/v1/service-category/{$whole}/includes", $user, [ 'child_category_uuid' => $hand, ]); self::assertSame(201, $this->responseCode()); $body = $this->authJson('GET', "/api/v1/service-category/{$whole}/includes", $user); self::assertCount(1, $body['data']); self::assertSame('دست', $body['data'][0]['name']); } public function testTheSameEdgeTwiceIsNotAnError(): void { [$user] = $this->clinic(); $whole = $this->category($user, 'تمام بدن'); $hand = $this->category($user, 'دست'); $this->authJson('POST', "/api/v1/service-category/{$whole}/includes", $user, ['child_category_uuid' => $hand]); // تکرار همان یال idempotent است: کاربر دوبار کلیک می‌کند، خطا معنایی ندارد. $this->authJson('POST', "/api/v1/service-category/{$whole}/includes", $user, ['child_category_uuid' => $hand]); self::assertSame(200, $this->responseCode()); self::assertCount(1, $this->authJson('GET', "/api/v1/service-category/{$whole}/includes", $user)['data']); } public function testAnEdgeCanBeRemoved(): void { [$user] = $this->clinic(); $whole = $this->category($user, 'تمام بدن'); $hand = $this->category($user, 'دست'); $this->authJson('POST', "/api/v1/service-category/{$whole}/includes", $user, ['child_category_uuid' => $hand]); $this->authJson('DELETE', "/api/v1/service-category/{$whole}/includes/{$hand}", $user); self::assertSame(200, $this->responseCode()); self::assertSame([], $this->authJson('GET', "/api/v1/service-category/{$whole}/includes", $user)['data']); } public function testAResourceTakesTheGlobalCategories(): void { [$user, $clinic, $address] = $this->clinic(); $type = new ResourceType('clinic', (int) $clinic->getId(), 'device', 'دستگاه'); $this->em->persist($type); $this->em->flush(); $resource = new ClinicResource($address, $type, 'لیزر دایود'); $this->em->persist($resource); $this->em->flush(); $hand = $this->category($user, 'دست'); $foot = $this->category($user, 'پا'); $body = $this->authJson('PUT', "/api/v1/resource/{$resource->getUuid()}/categories", $user, [ 'category_uuids' => [$hand, $foot], ]); self::assertSame(200, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE)); self::assertCount(2, $body['data']['categories']); // جایگزینی کامل: فهرست خالی یعنی هیچ دسته‌ای. $emptied = $this->authJson('PUT', "/api/v1/resource/{$resource->getUuid()}/categories", $user, ['category_uuids' => []]); self::assertSame([], $emptied['data']['categories']); } // ── ❌ خطا ─────────────────────────────────────────────────────────────── public function testACycleIsRefusedByTheEndpoint(): void { [$user] = $this->clinic(); $whole = $this->category($user, 'تمام بدن'); $hand = $this->category($user, 'دست'); $this->authJson('POST', "/api/v1/service-category/{$whole}/includes", $user, ['child_category_uuid' => $hand]); // «دست شامل تمام بدن» حلقه می‌بندد. $body = $this->authJson('POST', "/api/v1/service-category/{$hand}/includes", $user, ['child_category_uuid' => $whole]); self::assertSame(422, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE)); } public function testACategoryFromAnotherEnvironmentCannotBeAssigned(): void { [$user, $clinic, $address] = $this->clinic(); [$otherUser] = $this->clinic(); $type = new ResourceType('clinic', (int) $clinic->getId(), 'device', 'دستگاه'); $this->em->persist($type); $this->em->flush(); $resource = new ClinicResource($address, $type, 'لیزر'); $this->em->persist($resource); $this->em->flush(); $foreign = $this->category($otherUser, 'دستهٔ کلینیک دیگر'); $this->authJson('PUT', "/api/v1/resource/{$resource->getUuid()}/categories", $user, [ 'category_uuids' => [$foreign], ]); self::assertSame(422, $this->responseCode()); } public function testTheBodyMustCarryTheField(): void { [$user] = $this->clinic(); $whole = $this->category($user, 'تمام بدن'); $this->authJson('POST', "/api/v1/service-category/{$whole}/includes", $user, ['wrong' => 'x']); self::assertSame(422, $this->responseCode()); } }