176 lines
5.2 KiB
PHP
176 lines
5.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Service\Leave;
|
|
|
|
use App\Entity\ContractSuspension;
|
|
use App\Service\Leave\SuspensionDaysCalculator;
|
|
use DateTimeImmutable;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
final class SuspensionDaysCalculatorTest extends TestCase
|
|
{
|
|
public function testNoSuspensionsReturnsZero(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[]
|
|
);
|
|
|
|
self::assertSame(0, $result);
|
|
}
|
|
|
|
public function testFullMonthSuspension(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-03-01', '2026-03-31');
|
|
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[$suspension]
|
|
);
|
|
|
|
self::assertSame(31, $result);
|
|
}
|
|
|
|
public function testPartialMonthSuspension(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-03-10', '2026-03-20');
|
|
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[$suspension]
|
|
);
|
|
|
|
self::assertSame(11, $result);
|
|
}
|
|
|
|
public function testSuspensionSpanningMultipleMonths(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-02-15', '2026-04-10');
|
|
|
|
// March fully covered
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[$suspension]
|
|
);
|
|
|
|
self::assertSame(31, $result);
|
|
}
|
|
|
|
public function testSuspensionWithoutEndDate(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-03-15', null);
|
|
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[$suspension]
|
|
);
|
|
|
|
self::assertSame(17, $result);
|
|
}
|
|
|
|
public function testMultipleSuspensionsInSameMonth(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$s1 = $this->buildSuspension('2026-03-01', '2026-03-10');
|
|
$s2 = $this->buildSuspension('2026-03-20', '2026-03-25');
|
|
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[$s1, $s2]
|
|
);
|
|
|
|
self::assertSame(16, $result);
|
|
}
|
|
|
|
public function testSuspensionOutsideMonthReturnsZero(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-01-01', '2026-01-31');
|
|
|
|
$result = $calc->countSuspendedDaysInMonth(
|
|
new DateTimeImmutable('2026-03-01'),
|
|
new DateTimeImmutable('2026-03-31'),
|
|
[$suspension]
|
|
);
|
|
|
|
self::assertSame(0, $result);
|
|
}
|
|
|
|
public function testCountSuspendedBusinessDays(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
// March 2-6, 2026 = Mon-Fri = 5 business days
|
|
$suspension = $this->buildSuspension('2026-03-02', '2026-03-06');
|
|
|
|
$result = $calc->countSuspendedBusinessDays(
|
|
new DateTimeImmutable('2026-01-01'),
|
|
new DateTimeImmutable('2026-12-31'),
|
|
[$suspension],
|
|
[]
|
|
);
|
|
|
|
self::assertSame(5, $result);
|
|
}
|
|
|
|
public function testFirstMonthGraceShiftsStartByOneMonth(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-03-15', '2026-06-30');
|
|
|
|
$result = $calc->applyFirstMonthGrace([$suspension]);
|
|
|
|
self::assertCount(1, $result);
|
|
self::assertEquals(new DateTimeImmutable('2026-04-15'), $result[0]->getStartDate());
|
|
self::assertEquals(new DateTimeImmutable('2026-06-30'), $result[0]->getEndDate());
|
|
}
|
|
|
|
public function testFirstMonthGraceRemovesSuspensionShorterThanOneMonth(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-03-10', '2026-03-25');
|
|
|
|
$result = $calc->applyFirstMonthGrace([$suspension]);
|
|
|
|
self::assertCount(0, $result);
|
|
}
|
|
|
|
public function testFirstMonthGraceOpenEndedSuspension(): void
|
|
{
|
|
$calc = new SuspensionDaysCalculator();
|
|
$suspension = $this->buildSuspension('2026-03-01', null);
|
|
|
|
$result = $calc->applyFirstMonthGrace([$suspension]);
|
|
|
|
self::assertCount(1, $result);
|
|
self::assertEquals(new DateTimeImmutable('2026-04-01'), $result[0]->getStartDate());
|
|
self::assertNull($result[0]->getEndDate());
|
|
}
|
|
|
|
private function buildSuspension(string $start, ?string $end): ContractSuspension
|
|
{
|
|
$s = new ContractSuspension();
|
|
$s->setStartDate(new DateTimeImmutable($start));
|
|
if (null !== $end) {
|
|
$s->setEndDate(new DateTimeImmutable($end));
|
|
}
|
|
|
|
return $s;
|
|
}
|
|
}
|