setAccessible(true); $ref->setValue($rep, $id); return $rep; } private function policyReturning(?Representation $rep): RepresentationEditPolicy { $repo = $this->createStub(RepresentationRepository::class); $repo->method('findByUser')->willReturn($rep); return new RepresentationEditPolicy($repo); } private function doctorOwnedBy(?int $representationId): Doctor { $doctor = new Doctor(new User('09120000001'), 'پزشک آزمون'); $doctor->setRepresentationId($representationId); return $doctor; } private function clinicOwnedBy(?int $representationId): Clinic { $clinic = new Clinic(new User('09120000002')); $clinic->setRepresentationId($representationId); return $clinic; } // ── مالکیت ──────────────────────────────────────────────────────────────── public function testRepresentationOwningTheDoctorIsAllowed(): void { $user = new User('09120000003'); $user->setRoles(['ROLE_USER', 'ROLE_REPRESENTATION']); $policy = $this->policyReturning($this->repWithId($user, 7)); self::assertTrue($policy->ownsDoctor($user, $this->doctorOwnedBy(7))); } public function testAnotherRepresentationIsRejected(): void { $user = new User('09120000004'); $user->setRoles(['ROLE_USER', 'ROLE_REPRESENTATION']); $policy = $this->policyReturning($this->repWithId($user, 7)); self::assertFalse($policy->ownsDoctor($user, $this->doctorOwnedBy(8))); } public function testDoctorWithoutRepresentationIsNeverOwned(): void { $user = new User('09120000005'); $user->setRoles(['ROLE_USER', 'ROLE_REPRESENTATION']); $policy = $this->policyReturning($this->repWithId($user, 7)); self::assertFalse($policy->ownsDoctor($user, $this->doctorOwnedBy(null))); } public function testUserWithoutTheRoleIsRejectedWithoutHittingTheRepository(): void { $user = new User('09120000006'); $user->setRoles(['ROLE_USER']); $repo = $this->createMock(RepresentationRepository::class); $repo->expects(self::never())->method('findByUser'); $policy = new RepresentationEditPolicy($repo); self::assertFalse($policy->ownsDoctor($user, $this->doctorOwnedBy(7))); } public function testRoleWithoutRepresentationRowIsRejectedNotFatal(): void { $user = new User('09120000007'); $user->setRoles(['ROLE_USER', 'ROLE_REPRESENTATION']); $policy = $this->policyReturning(null); self::assertFalse($policy->ownsDoctor($user, $this->doctorOwnedBy(7))); } public function testClinicOwnershipFollowsTheSameRule(): void { $user = new User('09120000008'); $user->setRoles(['ROLE_USER', 'ROLE_REPRESENTATION']); $policy = $this->policyReturning($this->repWithId($user, 3)); self::assertTrue($policy->ownsClinic($user, $this->clinicOwnedBy(3))); self::assertFalse($policy->ownsClinic($user, $this->clinicOwnedBy(4))); } // ── whitelist ───────────────────────────────────────────────────────────── public function testForbiddenClinicFieldIsNamed(): void { $policy = $this->policyReturning(null); self::assertSame( 'doctors', $policy->firstForbiddenField(['info' => 'x', 'doctors' => []], RepresentationEditPolicy::CLINIC_FIELDS), ); } public function testAllowedClinicPayloadPasses(): void { $policy = $this->policyReturning(null); self::assertNull( $policy->firstForbiddenField( ['info' => 'x', 'clinic_logo' => 'https://a/b.png', '24_7' => true], RepresentationEditPolicy::CLINIC_FIELDS, ), ); } public function testForbiddenDoctorFieldsAreNamed(): void { $policy = $this->policyReturning(null); self::assertSame( 'medical_system_code', $policy->firstForbiddenField(['medical_system_code' => '123'], RepresentationEditPolicy::DOCTOR_FIELDS), ); self::assertSame( 'active', $policy->firstForbiddenField(['info' => 'x', 'active' => true], RepresentationEditPolicy::DOCTOR_FIELDS), ); } public function testEmptyPayloadHasNoForbiddenField(): void { $policy = $this->policyReturning(null); self::assertNull($policy->firstForbiddenField([], RepresentationEditPolicy::DOCTOR_FIELDS)); } }