em = self::getContainer()->get(EntityManagerInterface::class); // Employé dédié au test. $this->employee = new User(); $this->employee->setUsername('mcp-test-employee-'.uniqid()); $this->employee->setPassword('x'); $this->employee->setRoles(['ROLE_USER']); $this->employee->setIsEmployee(true); $this->employee->setReferencePeriodStart('06-01'); $this->em->persist($this->employee); $this->admin = new User(); $this->admin->setUsername('mcp-test-admin-'.uniqid()); $this->admin->setPassword('x'); $this->admin->setRoles(['ROLE_ADMIN']); $this->em->persist($this->admin); // Policy CP active (créée si absente — findOneByType peut déjà exister via fixtures). $policy = $this->em->getRepository(AbsencePolicy::class)->findOneBy(['type' => AbsenceType::PaidLeave]); if (null === $policy) { $policy = new AbsencePolicy(); $policy->setType(AbsenceType::PaidLeave); $policy->setCountWorkingDaysOnly(true); $policy->setActive(true); $this->em->persist($policy); } else { $policy->setActive(true); } $this->em->flush(); } public function testCreateReservesPendingDays(): void { $tool = $this->createTool($this->admin); // Lundi 2026-06-01 → vendredi 2026-06-05 = 5 jours ouvrés. $json = ($tool)( $this->employee->getId(), 'cp', '2026-06-01', '2026-06-05', ); $data = json_decode($json, true); self::assertSame('pending', $data['status']); // JSON ne préserve pas le type float pour un entier (5.0 -> 5) : on compare la valeur. self::assertSame(5.0, (float) $data['countedDays']); self::assertSame($this->employee->getId(), $data['user']['id']); $balance = self::getContainer()->get(AbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; self::assertNotNull($balance); self::assertSame(5.0, $balance->getPending()); } public function testApproveMovesPendingToTaken(): void { $created = json_decode( ($this->createTool($this->admin))($this->employee->getId(), 'cp', '2026-06-01', '2026-06-05'), true, ); $json = ($this->reviewTool($this->admin))($created['id'], 'approve'); $data = json_decode($json, true); self::assertSame('approved', $data['status']); self::assertSame($this->admin->getId(), $data['reviewedBy']['id']); $balance = self::getContainer()->get(AbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; self::assertSame(0.0, $balance->getPending()); self::assertSame(5.0, $balance->getTaken()); } public function testAdminCancelApprovedReleasesTaken(): void { $created = json_decode( ($this->createTool($this->admin))($this->employee->getId(), 'cp', '2026-06-01', '2026-06-05'), true, ); ($this->reviewTool($this->admin))($created['id'], 'approve'); $data = json_decode(($this->cancelTool($this->admin))($created['id']), true); self::assertSame('cancelled', $data['status']); $balance = self::getContainer()->get(AbsenceBalanceRepository::class) ->findOneForPeriod($this->employee, AbsenceType::PaidLeave, '2026-2027') ; self::assertSame(0.0, $balance->getTaken()); self::assertSame(0.0, $balance->getPending()); } private function securityFor(User $user): Security { $security = $this->createMock(Security::class); $security->method('isGranted')->willReturn(true); $security->method('getUser')->willReturn($user); return $security; } private function createTool(User $actor): CreateAbsenceRequestTool { $c = self::getContainer(); return new CreateAbsenceRequestTool( $c->get(EntityManagerInterface::class), $c->get(UserRepository::class), $c->get(AbsencePolicyRepository::class), $c->get(AbsenceRequestRepository::class), $c->get(AbsenceDayCalculator::class), $c->get(AbsenceBalanceService::class), $this->securityFor($actor), ); } private function reviewTool(User $actor): ReviewAbsenceRequestTool { $c = self::getContainer(); return new ReviewAbsenceRequestTool( $c->get(EntityManagerInterface::class), $c->get(AbsenceRequestRepository::class), $c->get(AbsenceBalanceService::class), $this->securityFor($actor), ); } private function cancelTool(User $actor): CancelAbsenceRequestTool { $c = self::getContainer(); return new CancelAbsenceRequestTool( $c->get(EntityManagerInterface::class), $c->get(AbsenceRequestRepository::class), $c->get(AbsenceBalanceService::class), $this->securityFor($actor), ); } }