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>
85 lines
3.2 KiB
PHP
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;
|
|
}
|
|
}
|