ldc-arcadia-api/tests/Integration/Infra/Adapters/Directories/EloquentEmployeeDirectoryTest.php
Jérémy Munsch 53b0dd9f1e
feat(employees): implement filtering and sorting for employee retrieval
Added Filter and Sorter classes to handle employee filtering and sorting criteria. Updated FindAllEmployees use case to utilize these new classes for improved employee data retrieval.
2026-08-14 09:30:21 +02:00

200 lines
8.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Integration\Infra\Adapters\Directories;
use Domain\Models\Entities\Employee;
use Domain\Models\ValueObjects\Entities\ArcadiaEmployeeId;
use Domain\Models\ValueObjects\EstablishmentCode;
use Domain\Models\ValueObjects\ServiceId;
use Domain\Models\ValueObjects\SiteId;
use Domain\Models\ValueObjects\Employees\EmployeeFilter;
use Domain\Models\ValueObjects\Employees\EmployeeSortColumn;
use Domain\Models\ValueObjects\Employees\EmployeeSorter;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Infra\Adapters\Directories\EloquentEmployeeDirectory;
use Infra\Database\Models\Employee as EmployeeModel;
use Shared\Paginated;
use Shared\Pagination;
use Tests\TestCase;
uses(TestCase::class, RefreshDatabase::class);
covers(EloquentEmployeeDirectory::class);
beforeEach(function (): void {
EmployeeModel::query()->delete();
});
describe('EloquentEmployeeDirectory Integration Tests', function (): void {
it('finds an employee by public employee number and maps to domain entity', function (): void {
// GIVEN
$directory = new EloquentEmployeeDirectory();
EmployeeModel::factory()->create([
'public_employee_number' => '1234567',
'last_name' => 'DUPONT',
'first_name' => 'Jean',
'start_date' => '2024-01-01',
'end_date' => '2025-01-01',
'planned_end_date' => '2025-06-01',
'establishment' => '01',
'site' => 'LDCSER',
'service' => '097',
'created_at' => '2024-01-01 10:00:00',
'updated_at' => '2024-01-02 12:00:00',
]);
$employeeId = new ArcadiaEmployeeId('1234567');
// WHEN
$result = $directory->find($employeeId);
// THEN
expect($result)->toBeInstanceOf(Employee::class)
->and($result?->id()->value)->toBe('1234567')
->and($result?->lastName)->toBe('DUPONT')
->and($result?->firstName)->toBe('Jean')
->and($result?->startDate->format('Y-m-d'))->toBe('2024-01-01')
->and($result?->endDate?->format('Y-m-d'))->toBe('2025-01-01')
->and($result?->plannedEndDate?->format('Y-m-d'))->toBe('2025-06-01')
->and($result?->establishment->value)->toBe('01')
->and($result?->site->value)->toBe('LDCSER')
->and($result?->service->value)->toBe('097')
->and($result?->createdAt->format('Y-m-d H:i:s'))->toBe('2024-01-01 10:00:00')
->and($result?->updatedAt?->format('Y-m-d H:i:s'))->toBe('2024-01-02 12:00:00');
});
it('converts string dates to DateTimeInterface using toDateTime helper', function (): void {
// GIVEN
$directory = new EloquentEmployeeDirectory();
$reflection = new \ReflectionMethod(EloquentEmployeeDirectory::class, 'toDateTime');
// WHEN
/** @var \DateTimeInterface $result */
$result = $reflection->invoke($directory, '2024-01-15 14:30:00');
// THEN
expect($result)->toBeInstanceOf(\DateTimeInterface::class)
->and($result->format('Y-m-d H:i:s'))->toBe('2024-01-15 14:30:00');
});
it('returns null when employee is not found', function (): void {
// GIVEN
$directory = new EloquentEmployeeDirectory();
$employeeId = new ArcadiaEmployeeId('9999999');
// WHEN
$result = $directory->find($employeeId);
// THEN
expect($result)->toBeNull();
});
it('throws UnexpectedValueException when created_at is null', function (): void {
// GIVEN
$directory = new EloquentEmployeeDirectory();
EmployeeModel::query()->insert([
'public_employee_number' => '7654321',
'last_name' => 'MARTIN',
'first_name' => 'Alice',
'start_date' => '2024-01-01',
'establishment' => '01',
'site' => 'LDCSER',
'service' => '097',
'created_at' => null,
'updated_at' => null,
]);
$employeeId = new ArcadiaEmployeeId('7654321');
// WHEN & THEN
expect(fn () => $directory->find($employeeId))
->toThrow(\UnexpectedValueException::class, 'Employee created_at cannot be null.');
});
it('filters employees when EmployeeFilter parameters are provided', function (): void {
// GIVEN
$directory = new EloquentEmployeeDirectory();
EmployeeModel::factory()->create([
'public_employee_number' => '1000001',
'establishment' => '01',
'site' => 'LDCSER',
'service' => '097',
'created_at' => '2024-01-01 08:00:00',
'updated_at' => '2024-01-01 09:00:00',
]);
EmployeeModel::factory()->create([
'public_employee_number' => '1000002',
'establishment' => 'LY',
'site' => 'LDCSER',
'service' => '101',
'created_at' => '2024-01-01 08:00:00',
'updated_at' => '2024-01-01 09:00:00',
]);
$filter = new EmployeeFilter(
establishment: new EstablishmentCode('01'),
sites: [new SiteId('LDCSER')],
service: new ServiceId('097'),
since: new \DateTimeImmutable('2024-01-01 00:00:00')
);
$pagination = Pagination::ofPage(1, 10);
$sorter = new EmployeeSorter(EmployeeSortColumn::arcadiaId, \SortDirection::Ascending);
// WHEN
$result = $directory->findAll($pagination, $sorter, $filter);
// THEN
expect($result)->toBeInstanceOf(Paginated::class)
->and($result->getTotal())->toBe(1)
->and(count($result->getItems()))->toBe(1)
->and($result->getItems()[0]->id()->value)->toBe('1000001');
});
it('returns paginated employees sorted by specified columns', function (EmployeeSortColumn $sortColumn, \SortDirection $direction): void {
// GIVEN
$directory = new EloquentEmployeeDirectory();
EmployeeModel::factory()->create([
'public_employee_number' => '1000001',
'start_date' => '2024-01-01',
'end_date' => '2024-06-01',
'planned_end_date' => '2024-12-01',
'created_at' => '2024-01-01 08:00:00',
'updated_at' => '2024-01-01 09:00:00',
]);
EmployeeModel::factory()->create([
'public_employee_number' => '1000002',
'start_date' => '2024-02-01',
'end_date' => '2024-07-01',
'planned_end_date' => '2024-12-15',
'created_at' => '2024-02-01 08:00:00',
'updated_at' => '2024-02-01 09:00:00',
]);
$pagination = Pagination::ofPage(1, 10);
$sorter = new EmployeeSorter($sortColumn, $direction);
// WHEN
$result = $directory->findAll($pagination, $sorter);
// THEN
expect($result)->toBeInstanceOf(Paginated::class)
->and($result->getTotal())->toBe(2)
->and(count($result->getItems()))->toBe(2);
})->with([
'arcadiaId asc' => [EmployeeSortColumn::arcadiaId, \SortDirection::Ascending],
'arcadiaId desc' => [EmployeeSortColumn::arcadiaId, \SortDirection::Descending],
'startDate asc' => [EmployeeSortColumn::startDate, \SortDirection::Ascending],
'endDate desc' => [EmployeeSortColumn::endDate, \SortDirection::Descending],
'plannedEndDate asc' => [EmployeeSortColumn::plannedEndDate, \SortDirection::Ascending],
'createdAt desc' => [EmployeeSortColumn::createdAt, \SortDirection::Descending],
'updatedAt asc' => [EmployeeSortColumn::updatedAt, \SortDirection::Ascending],
]);
});