144 lines
5.4 KiB
PHP
144 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Entity;
|
|
|
|
use App\Entity\JobProfile;
|
|
use App\Entity\SeasonAssignment;
|
|
use App\Entity\SeasonAssignmentTask;
|
|
use App\Entity\Teamer;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class SeasonAssignmentTest extends TestCase
|
|
{
|
|
public function testANewSeasonAssignmentCarriesItsOwnUuid(): void
|
|
{
|
|
$first = new SeasonAssignment();
|
|
$second = new SeasonAssignment();
|
|
|
|
$this->assertMatchesRegularExpression('/^[0-9a-f-]{36}$/', $first->getUuid());
|
|
$this->assertNotSame($first->getUuid(), $second->getUuid());
|
|
}
|
|
|
|
public function testANewSeasonAssignmentIsNotDeleted(): void
|
|
{
|
|
$this->assertFalse((new SeasonAssignment())->isDeleted());
|
|
}
|
|
|
|
/**
|
|
* The list only ever hides soft-deleted records, so deleting must not detach the teamer -
|
|
* the placement has to stay readable for whoever looks at it afterwards.
|
|
*/
|
|
public function testSoftDeletingKeepsTheRecordIntact(): void
|
|
{
|
|
$teamer = (new Teamer())->setFirstName('Ada')->setLastName('Musterfrau');
|
|
$seasonAssignment = (new SeasonAssignment())->setTeamer($teamer);
|
|
|
|
$seasonAssignment->setDeleted();
|
|
|
|
$this->assertTrue($seasonAssignment->isDeleted());
|
|
$this->assertSame($teamer, $seasonAssignment->getTeamer());
|
|
}
|
|
|
|
public function testTheInverseSideIsKeptInSync(): void
|
|
{
|
|
$teamer = new Teamer();
|
|
$seasonAssignment = new SeasonAssignment();
|
|
|
|
$teamer->addSeasonAssignment($seasonAssignment);
|
|
|
|
$this->assertCount(1, $teamer->getSeasonAssignments());
|
|
$this->assertSame($teamer, $seasonAssignment->getTeamer());
|
|
|
|
// adding the same one twice must not duplicate it
|
|
$teamer->addSeasonAssignment($seasonAssignment);
|
|
$this->assertCount(1, $teamer->getSeasonAssignments());
|
|
|
|
$teamer->removeSeasonAssignment($seasonAssignment);
|
|
$this->assertCount(0, $teamer->getSeasonAssignments());
|
|
$this->assertNull($seasonAssignment->getTeamer());
|
|
}
|
|
|
|
/**
|
|
* Administrative users lay the season's assignments out first and place teamers on them
|
|
* later, so an assignment without a teamer is a normal state rather than a half built one.
|
|
*/
|
|
public function testAnAssignmentStartsWithoutATeamer(): void
|
|
{
|
|
$seasonAssignment = new SeasonAssignment();
|
|
|
|
$this->assertNull($seasonAssignment->getTeamer());
|
|
}
|
|
|
|
public function testATeamerCanBePlacedAndRemovedAgain(): void
|
|
{
|
|
$teamer = (new Teamer())->setFirstName('Ada')->setLastName('Musterfrau');
|
|
$seasonAssignment = new SeasonAssignment();
|
|
|
|
$seasonAssignment->setTeamer($teamer);
|
|
$this->assertSame($teamer, $seasonAssignment->getTeamer());
|
|
|
|
$seasonAssignment->setTeamer(null);
|
|
$this->assertNull($seasonAssignment->getTeamer());
|
|
}
|
|
|
|
/**
|
|
* The period and the house live on the assignment itself - it is not cut from a travel, so
|
|
* there is no Destination to read them from.
|
|
*/
|
|
public function testItCarriesItsOwnPeriodAndHouse(): void
|
|
{
|
|
$seasonAssignment = (new SeasonAssignment())
|
|
->setTeamer((new Teamer())->setFirstName('Ada')->setLastName('Musterfrau'))
|
|
->setDateFrom(new \DateTimeImmutable('2026-11-01'))
|
|
->setDateTo(new \DateTimeImmutable('2027-04-30'))
|
|
->setHotelCode('AGR')
|
|
->setJobProfile((new JobProfile())->setName('Guide'))
|
|
;
|
|
|
|
$this->assertSame('2026-11-01', $seasonAssignment->getDateFrom()->format('Y-m-d'));
|
|
$this->assertSame('2027-04-30', $seasonAssignment->getDateTo()->format('Y-m-d'));
|
|
$this->assertSame('AGR', $seasonAssignment->getHotelCode());
|
|
}
|
|
|
|
public function testApplyingDeadlinesCopiesBothOverridesOntoOpenEntriesOnly(): void
|
|
{
|
|
$seasonAssignment = new SeasonAssignment();
|
|
$source = (new SeasonAssignmentTask())
|
|
->setDeadlineOverride1(new \DateTimeImmutable('2026-11-15'))
|
|
->setDeadlineOverride2(new \DateTimeImmutable('2026-11-30'));
|
|
$open = new SeasonAssignmentTask();
|
|
$done = (new SeasonAssignmentTask())
|
|
->setDone(true)
|
|
->setDeadlineOverride1(new \DateTimeImmutable('2026-10-01'));
|
|
$seasonAssignment->addTask($source)->addTask($open)->addTask($done);
|
|
|
|
$this->assertSame(1, $seasonAssignment->applyDeadlinesToOpenTasks($source));
|
|
|
|
$this->assertSame('2026-11-15', $open->getDeadlineOverride1()?->format('Y-m-d'));
|
|
$this->assertSame('2026-11-30', $open->getDeadlineOverride2()?->format('Y-m-d'));
|
|
$this->assertSame('2026-10-01', $done->getDeadlineOverride1()?->format('Y-m-d'));
|
|
$this->assertNull($done->getDeadlineOverride2());
|
|
}
|
|
|
|
/**
|
|
* Empty fields are applied as well: that is how the office resets every entry to its
|
|
* computed deadline in one go.
|
|
*/
|
|
public function testApplyingEmptyDeadlinesResetsTheOverrides(): void
|
|
{
|
|
$seasonAssignment = new SeasonAssignment();
|
|
$source = new SeasonAssignmentTask();
|
|
$other = (new SeasonAssignmentTask())
|
|
->setDeadlineOverride1(new \DateTimeImmutable('2026-11-15'))
|
|
->setDeadlineOverride2(new \DateTimeImmutable('2026-11-30'));
|
|
$seasonAssignment->addTask($source)->addTask($other);
|
|
|
|
$seasonAssignment->applyDeadlinesToOpenTasks($source);
|
|
|
|
$this->assertNull($other->getDeadlineOverride1());
|
|
$this->assertNull($other->getDeadlineOverride2());
|
|
}
|
|
}
|