Files
SIRH/tests/State/AbsencePrintProviderTest.php
tristan ddd1b8116e fix(calendar) : exclude departed employees from absence PDF print
The calendar view hides employees whose contract doesn't intersect the displayed
month, but the absence PDF print still listed them. Apply the same intersection
filter (hasContractInRange over [from, to]) in AbsencePrintProvider, and reject
invalid from/to dates. A employee who left in April no longer appears on a May print.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 08:26:20 +02:00

85 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\State;
use App\Entity\Employee;
use App\Entity\EmployeeContractPeriod;
use App\State\AbsencePrintProvider;
use DateTimeImmutable;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
/**
* The provider constructor takes final-class collaborators (Twig, repositories) that
* PHPUnit cannot double. The pure contract-range helper is exercised via
* newInstanceWithoutConstructor + reflection.
*
* @internal
*/
final class AbsencePrintProviderTest extends TestCase
{
public function testHasContractInRangeFalseWhenContractEndedBeforeRange(): void
{
$provider = new ReflectionClass(AbsencePrintProvider::class)->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'));
}
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;
}
}