newInstanceWithoutConstructor(); $employee = $this->buildEmployeeWithPeriod('2025-01-01', '2026-04-30'); // Imprime mai : l'employé parti le 30/04 ne doit pas être inclus. self::assertFalse($this->hasInRange($provider, $employee, '2026-05-01', '2026-05-31')); } public function testHasContractInRangeTrueWhenContractOverlapsRange(): void { $provider = new ReflectionClass(AbsencePrintProvider::class)->newInstanceWithoutConstructor(); $employee = $this->buildEmployeeWithPeriod('2025-01-01', '2026-05-15'); // Contrat finissant le 15/05 → chevauche le mois de mai → inclus. self::assertTrue($this->hasInRange($provider, $employee, '2026-05-01', '2026-05-31')); } public function testHasContractInRangeTrueForOpenEndedContract(): void { $provider = new ReflectionClass(AbsencePrintProvider::class)->newInstanceWithoutConstructor(); $employee = $this->buildEmployeeWithPeriod('2020-01-01', null); self::assertTrue($this->hasInRange($provider, $employee, '2026-05-01', '2026-05-31')); } public function testHasContractInRangeFalseWhenContractStartsAfterRange(): void { $provider = new ReflectionClass(AbsencePrintProvider::class)->newInstanceWithoutConstructor(); $employee = $this->buildEmployeeWithPeriod('2026-06-01', null); self::assertFalse($this->hasInRange($provider, $employee, '2026-05-01', '2026-05-31')); } public function testHasContractInRangeFalseWhenNoPeriods(): void { $provider = new ReflectionClass(AbsencePrintProvider::class)->newInstanceWithoutConstructor(); $employee = new Employee(); self::assertFalse($this->hasInRange($provider, $employee, '2026-05-01', '2026-05-31')); } public function testHasContractInRangeIncludesEmployeeEndingOnFromDayDespiteTimeComponent(): void { // Garde-fou : `from` portant une heure (cf. createFromFormat) ne doit pas exclure // un employé dont le contrat finit pile le jour de `from` (comparaison date seule). $provider = new ReflectionClass(AbsencePrintProvider::class)->newInstanceWithoutConstructor(); $employee = $this->buildEmployeeWithPeriod('2025-01-01', '2026-05-01'); $result = new ReflectionClass($provider::class) ->getMethod('hasContractInRange') ->invoke($provider, $employee, new DateTimeImmutable('2026-05-01 08:33:53'), new DateTimeImmutable('2026-05-31 23:59:59')) ; self::assertTrue($result); } private function hasInRange(object $provider, Employee $employee, string $from, string $to): bool { return new ReflectionClass($provider::class) ->getMethod('hasContractInRange') ->invoke($provider, $employee, new DateTimeImmutable($from), new DateTimeImmutable($to)) ; } private function buildEmployeeWithPeriod(string $start, ?string $end): Employee { $employee = new Employee(); $period = new EmployeeContractPeriod(); $period->setEmployee($employee); $period->setStartDate(new DateTimeImmutable($start)); $period->setEndDate(null !== $end ? new DateTimeImmutable($end) : null); $employee->getContractPeriods()->add($period); return $employee; } }