Files
myep-team/tests/Service/Assignment/AssignmentGeneratorTest.php
T

175 lines
6.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Service\Assignment;
use App\Entity\Assignment;
use App\Entity\Destination;
use App\Entity\Fee;
use App\Entity\JobProfile;
use App\Entity\StaffingRule;
use App\Enum\StaffingFee;
use App\Enum\StaffingRole;
use App\Model\PlannedAssignment;
use App\Model\StaffingCandidate;
use App\Repository\AssignmentRepository;
use App\Repository\DestinationRepository;
use App\Repository\StaffingRuleRepository;
use App\Service\Assignment\AssignmentGenerator;
use App\Service\Assignment\AssignmentPlanner;
use App\Service\Assignment\StaffingResolver;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
class AssignmentGeneratorTest extends TestCase
{
public function testThePreviewSeesDisabledRowsAndTheCommandDoesNot(): void
{
$enabled = self::rule('DKIMP', enabled: true);
$disabled = self::rule('DGSMP', enabled: false);
$asked = [];
$destinationRepository = $this->createStub(DestinationRepository::class);
$destinationRepository->method('getStaffingCandidates')->willReturnCallback(
static function (array $productCodes) use (&$asked): array {
$asked[] = $productCodes;
return [];
}
);
$generator = $this->generator([$enabled, $disabled], $destinationRepository);
$generator->getCandidates(enabledOnly: false);
$generator->getCandidates(enabledOnly: true);
$this->assertSame([['DKIMP', 'DGSMP'], ['DKIMP']], $asked);
}
public function testADateWithAnAssignmentIsMarkedSkipped(): void
{
$staffed = self::destination(1, 'DKIMP');
$open = self::destination(2, 'DKIMP');
$destinationRepository = $this->createStub(DestinationRepository::class);
$destinationRepository->method('getStaffingCandidates')->willReturn([$staffed, $open]);
$assignmentRepository = $this->createStub(AssignmentRepository::class);
$assignmentRepository->method('getDestinationIdsWithAnyAssignment')->willReturn([1]);
$candidates = $this
->generator([self::rule('DKIMP', enabled: true)], $destinationRepository, $assignmentRepository)
->getCandidates(enabledOnly: true)
;
$this->assertTrue($candidates[0]->skipped);
$this->assertFalse($candidates[1]->skipped);
}
public function testGenerateBuildsDraftsFromThePlan(): void
{
$destination = self::destination(1, 'DKIMP');
$guide = new JobProfile();
$course = new JobProfile();
$guidingFee = new Fee();
$courseFee = new Fee();
$resolver = $this->createStub(StaffingResolver::class);
$resolver->method('jobProfile')->willReturnCallback(
static fn (StaffingRole $role): JobProfile => StaffingRole::GUIDE === $role ? $guide : $course
);
$resolver->method('fee')->willReturnCallback(
static fn (StaffingFee $fee): Fee => StaffingFee::GUIDING === $fee ? $guidingFee : $courseFee
);
$persisted = [];
$entityManager = $this->createMock(EntityManagerInterface::class);
$entityManager->method('persist')->willReturnCallback(static function (object $entity) use (&$persisted): void {
$persisted[] = $entity;
});
$entityManager->expects($this->once())->method('flush');
$generator = $this->generator([], resolver: $resolver, entityManager: $entityManager);
$assignments = $generator->generate(new StaffingCandidate($destination, self::rule('DKIMP', enabled: true), [
new PlannedAssignment(StaffingRole::GUIDE, 2, 5, [StaffingFee::GUIDING]),
new PlannedAssignment(StaffingRole::SKI_BEGINNER, 1, null, [StaffingFee::COURSE]),
], false));
$this->assertSame($persisted, $assignments);
$this->assertCount(2, $assignments);
$this->assertSame($destination, $assignments[0]->getDestination());
$this->assertSame($guide, $assignments[0]->getJobProfile());
$this->assertSame(2, $assignments[0]->getAvailableDispositions());
$this->assertSame(5, $assignments[0]->getPickup());
$this->assertSame([$guidingFee], $assignments[0]->getFees()->toArray());
$this->assertSame(Assignment::STATUS_DRAFT, $assignments[0]->getStatus());
$this->assertSame($course, $assignments[1]->getJobProfile());
$this->assertSame(0, $assignments[1]->getPickup());
$this->assertSame([$courseFee], $assignments[1]->getFees()->toArray());
}
public function testASkippedCandidateGeneratesNothing(): void
{
$entityManager = $this->createMock(EntityManagerInterface::class);
$entityManager->expects($this->never())->method('persist');
$entityManager->expects($this->never())->method('flush');
$assignments = $this->generator([], entityManager: $entityManager)->generate(new StaffingCandidate(
self::destination(1, 'DKIMP'),
self::rule('DKIMP', enabled: true),
[new PlannedAssignment(StaffingRole::GUIDE, 1)],
true,
));
$this->assertSame([], $assignments);
}
/**
* @param list<StaffingRule> $rules
*/
private function generator(
array $rules,
?DestinationRepository $destinationRepository = null,
?AssignmentRepository $assignmentRepository = null,
?StaffingResolver $resolver = null,
?EntityManagerInterface $entityManager = null,
): AssignmentGenerator {
$staffingRuleRepository = $this->createStub(StaffingRuleRepository::class);
$staffingRuleRepository->method('getList')->willReturn($rules);
if (null === $assignmentRepository) {
$assignmentRepository = $this->createStub(AssignmentRepository::class);
$assignmentRepository->method('getDestinationIdsWithAnyAssignment')->willReturn([]);
}
return new AssignmentGenerator(
$staffingRuleRepository,
$destinationRepository ?? $this->createStub(DestinationRepository::class),
$assignmentRepository,
new AssignmentPlanner(),
$resolver ?? $this->createStub(StaffingResolver::class),
$entityManager ?? $this->createStub(EntityManagerInterface::class),
new NullLogger(),
);
}
private static function rule(string $productCode, bool $enabled): StaffingRule
{
return (new StaffingRule())->setProductCode($productCode)->setGuides(1)->setEnabled($enabled);
}
private static function destination(int $id, string $productCode): Destination
{
$destination = (new Destination())->setProductCode($productCode)->setCode($productCode.'110127');
(new \ReflectionProperty(Destination::class, 'id'))->setValue($destination, $id);
return $destination;
}
}