feat : ajout des TU

This commit is contained in:
2026-02-19 22:06:54 +01:00
parent e8afd25566
commit d5230f685e
16 changed files with 684 additions and 19 deletions

View File

@@ -0,0 +1,156 @@
<?php
declare(strict_types=1);
namespace App\Tests\State;
use ApiPlatform\Metadata\Get;
use App\Entity\Absence;
use App\Entity\AbsenceType;
use App\Entity\Contract;
use App\Entity\Employee;
use App\Entity\User;
use App\Entity\WorkHour;
use App\Enum\HalfDay;
use App\Repository\Contract\AbsenceReadRepositoryInterface;
use App\Repository\Contract\EmployeeScopedRepositoryInterface;
use App\Repository\Contract\WorkHourReadRepositoryInterface;
use App\Service\WorkHours\AbsenceSegmentsResolver;
use App\Service\WorkHours\WorkedHoursCreditPolicy;
use App\State\WorkHourWeeklySummaryProvider;
use DateTime;
use DateTimeImmutable;
use PHPUnit\Framework\TestCase;
use ReflectionObject;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
/**
* @internal
*/
final class WorkHourWeeklySummaryProviderTest extends TestCase
{
private Security $security;
private EmployeeScopedRepositoryInterface $employeeRepository;
private WorkHourReadRepositoryInterface $workHourRepository;
private AbsenceReadRepositoryInterface $absenceRepository;
private RequestStack $requestStack;
protected function setUp(): void
{
$this->security = $this->createStub(Security::class);
$this->employeeRepository = $this->createStub(EmployeeScopedRepositoryInterface::class);
$this->workHourRepository = $this->createStub(WorkHourReadRepositoryInterface::class);
$this->absenceRepository = $this->createStub(AbsenceReadRepositoryInterface::class);
$this->requestStack = new RequestStack();
}
public function testThrowsWhenAnonymous(): void
{
$this->security->method('getUser')->willReturn(null);
$provider = new WorkHourWeeklySummaryProvider(
$this->security,
$this->requestStack,
$this->employeeRepository,
$this->workHourRepository,
$this->absenceRepository,
new AbsenceSegmentsResolver(),
new WorkedHoursCreditPolicy()
);
$this->expectException(AccessDeniedHttpException::class);
$provider->provide(new Get());
}
public function testBuildsWeeklyRowsWithOvertimeAndPresence(): void
{
$user = new User();
$timeEmployee = $this->buildEmployee(1, 'TIME', 35, 'Alice');
$presenceEmployee = $this->buildEmployee(2, 'PRESENCE', null, 'Bob');
$employees = [$timeEmployee, $presenceEmployee];
$workHours = [];
foreach (['2026-02-16', '2026-02-17', '2026-02-18', '2026-02-19', '2026-02-20'] as $date) {
$workHours[] = new WorkHour()
->setEmployee($timeEmployee)
->setWorkDate(new DateTimeImmutable($date))
->setMorningFrom('09:00')
->setMorningTo('19:00')
;
}
$absenceType = new AbsenceType()
->setCode('CP')
->setLabel('Congé')
->setColor('#000')
->setCountAsWorkedHours(true)
;
$presenceAbsence = new Absence()
->setEmployee($presenceEmployee)
->setType($absenceType)
->setStartDate(new DateTime('2026-02-16'))
->setEndDate(new DateTime('2026-02-16'))
->setStartHalf(HalfDay::AM)
->setEndHalf(HalfDay::PM)
;
$this->requestStack->push(new Request(query: ['weekStart' => '2026-02-16']));
$this->security->method('getUser')->willReturn($user);
$this->employeeRepository->method('findScoped')->with($user)->willReturn($employees);
$this->workHourRepository->method('findByDateRangeAndEmployees')->willReturn($workHours);
$this->absenceRepository->method('findForPrint')->willReturn([$presenceAbsence]);
$provider = new WorkHourWeeklySummaryProvider(
$this->security,
$this->requestStack,
$this->employeeRepository,
$this->workHourRepository,
$this->absenceRepository,
new AbsenceSegmentsResolver(),
new WorkedHoursCreditPolicy()
);
$result = $provider->provide(new Get());
self::assertSame('2026-02-16', $result->weekStart);
self::assertSame('2026-02-22', $result->weekEnd);
self::assertCount(2, $result->rows);
self::assertSame(3000, $result->rows[0]['weeklyTotalMinutes']);
self::assertSame(900, $result->rows[0]['weeklyOvertimeTotalMinutes']);
self::assertSame(120, $result->rows[0]['weeklyOvertime25Minutes']);
self::assertSame(210, $result->rows[0]['weeklyOvertime50Minutes']);
self::assertSame(1230, $result->rows[0]['weeklyRecoveryMinutes']);
self::assertSame(1.0, $result->rows[1]['weeklyPresenceCount']);
self::assertSame(0, $result->rows[1]['weeklyOvertimeTotalMinutes']);
}
private function buildEmployee(int $id, string $trackingMode, ?int $weeklyHours, string $firstName): Employee
{
$contract = new Contract()
->setName($trackingMode)
->setTrackingMode($trackingMode)
->setWeeklyHours($weeklyHours)
;
$employee = new Employee()
->setFirstName($firstName)
->setLastName('Test')
->setContract($contract)
;
$this->setEntityId($employee, $id);
return $employee;
}
private function setEntityId(object $entity, int $id): void
{
$reflection = new ReflectionObject($entity);
$property = $reflection->getProperty('id');
$property->setAccessible(true);
$property->setValue($entity, $id);
}
}