Files
hr/tests/Feature/Import/EmployeeImportTest.php
2026-07-30 17:24:40 +05:00

123 lines
4.0 KiB
PHP

<?php
declare(strict_types=1);
use App\DTOs\Import\EmployeeRowDto;
use App\Enums\ImportType;
use App\Models\Department;
use App\Models\Employee;
use App\Models\Position;
use App\Models\Shift;
use App\Services\Import\EmployeeImportTransformer;
use App\Services\Import\ImportService;
beforeEach(function (): void {
$this->department = Department::factory()->create(['name' => 'Engineering', 'code' => 'ENG']);
$this->position = Position::factory()->create(['name' => 'Developer']);
$this->shift = Shift::factory()->create(['name' => 'Day Shift', 'code' => 'DAY']);
$this->importService = app(ImportService::class);
$this->transformer = app(EmployeeImportTransformer::class);
});
it('skips duplicate employees during import', function (): void {
Employee::factory()->create([
'employee_number' => 'EMP-90001',
'national_id' => '1234567890',
]);
$rows = [[
'employee_number' => 'EMP-90001',
'full_name' => 'Duplicate Employee',
'national_id' => '1234567890',
'department' => 'Engineering',
'position' => 'Developer',
'shift' => 'Day Shift',
'hire_date' => '2024-01-01',
]];
$result = $this->importService->import(ImportType::Employees, $rows);
expect($result->imported)->toBe(0)
->and($result->skipped)->toBe(1)
->and($result->failed)->toBe(0)
->and(Employee::query()->where('employee_number', 'EMP-90001')->count())->toBe(1);
});
it('imports valid employee rows', function (): void {
$rows = [[
'employee_number' => 'EMP-90002',
'full_name' => 'Jane Smith',
'gender' => 'female',
'birth_date' => '1990-01-15',
'department' => 'Engineering',
'position' => 'Developer',
'shift' => 'Day Shift',
'hire_date' => '2024-03-15',
]];
$result = $this->importService->import(ImportType::Employees, $rows);
expect($result->imported)->toBe(1)
->and($result->skipped)->toBe(0)
->and($result->failed)->toBe(0);
$this->assertDatabaseHas('employees', [
'employee_number' => 'EMP-90002',
'full_name' => 'Jane Smith',
'department_id' => $this->department->id,
]);
});
it('reports validation errors for invalid employee rows', function (): void {
$rows = [[
'employee_number' => '',
'full_name' => '',
'department' => 'Unknown Department',
]];
$result = $this->importService->import(ImportType::Employees, $rows);
expect($result->imported)->toBe(0)
->and($result->failed)->toBe(1)
->and($result->errors)->not->toBeEmpty();
});
it('validates required fields and unknown references', function (): void {
$dto = EmployeeRowDto::fromMappedRow([
'employee_number' => '',
'full_name' => '',
'department' => 'Missing Department',
'position' => 'Missing Position',
'shift' => 'Missing Shift',
]);
$errors = $this->transformer->validate($dto);
expect($errors)->toContain('Employee number is required.')
->and($errors)->toContain('Full name is required.')
->and($errors)->toContain('Department "Missing Department" was not found.')
->and($errors)->toContain('Position "Missing Position" was not found.')
->and($errors)->toContain('Shift "Missing Shift" was not found.');
});
it('detects duplicates by employee number or national id', function (): void {
Employee::factory()->create([
'employee_number' => 'EMP-80001',
'national_id' => '9988776655',
]);
$duplicateByNumber = EmployeeRowDto::fromMappedRow([
'employee_number' => 'EMP-80001',
'full_name' => 'Someone Else',
]);
$duplicateByNationalId = EmployeeRowDto::fromMappedRow([
'employee_number' => 'EMP-80002',
'full_name' => 'Another Person',
'national_id' => '9988776655',
]);
expect($this->transformer->isDuplicate($duplicateByNumber))->toBeTrue()
->and($this->transformer->isDuplicate($duplicateByNationalId))->toBeTrue();
});