170 lines
6.0 KiB
PHP
170 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Entity;
|
|
|
|
use App\Entity\Application;
|
|
use App\Entity\Assignment;
|
|
use App\Entity\Disposition;
|
|
use App\Entity\Teamer;
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* A called-off teamer is free again: the teamer views ask the assignment for the teamer's
|
|
* disposition to decide between "eingeteilt" and the application button, so a called-off
|
|
* disposition must not be handed out there.
|
|
*/
|
|
class AssignmentTest extends TestCase
|
|
{
|
|
public function testTheActiveDispositionOfATeamerIsReturned(): void
|
|
{
|
|
$assignment = new Assignment();
|
|
$teamer = new Teamer();
|
|
$disposition = $this->createDisposition($assignment, $teamer);
|
|
|
|
$this->assertSame($disposition, $assignment->getActiveDispositionByTeamer($teamer));
|
|
}
|
|
|
|
public function testACalledOffDispositionIsNotReturned(): void
|
|
{
|
|
$assignment = new Assignment();
|
|
$teamer = new Teamer();
|
|
|
|
$this
|
|
->createDisposition($assignment, $teamer)
|
|
->setStatus(Disposition::STATUS_CALLED_OFF)
|
|
;
|
|
|
|
$this->assertNull($assignment->getActiveDispositionByTeamer($teamer));
|
|
}
|
|
|
|
public function testTheDispositionOfAnotherTeamerIsNotReturned(): void
|
|
{
|
|
$assignment = new Assignment();
|
|
$this->createDisposition($assignment, new Teamer());
|
|
|
|
$this->assertNull($assignment->getActiveDispositionByTeamer(new Teamer()));
|
|
}
|
|
|
|
/**
|
|
* A teamer can be called off and disposed again on the same assignment, so both dispositions
|
|
* live side by side - the active one has to win.
|
|
*/
|
|
public function testTheActiveDispositionWinsOverACalledOffOne(): void
|
|
{
|
|
$assignment = new Assignment();
|
|
$teamer = new Teamer();
|
|
|
|
$this
|
|
->createDisposition($assignment, $teamer)
|
|
->setStatus(Disposition::STATUS_CALLED_OFF)
|
|
;
|
|
$disposition = $this->createDisposition($assignment, $teamer);
|
|
|
|
$this->assertSame($disposition, $assignment->getActiveDispositionByTeamer($teamer));
|
|
}
|
|
|
|
/**
|
|
* The "Busbegleitung ab" field stores 0 for "Keine Busbegleitung" as well as null.
|
|
*/
|
|
#[DataProvider('providePickups')]
|
|
public function testHasBusEscort(int|string|null $pickup, bool $expected): void
|
|
{
|
|
$this->assertSame($expected, (new Assignment())->setPickup($pickup)->hasBusEscort());
|
|
}
|
|
|
|
public static function providePickups(): iterable
|
|
{
|
|
yield 'none' => [null, false];
|
|
yield 'zero' => [0, false];
|
|
yield 'empty form value' => ['', false];
|
|
yield 'pickup' => [4711, true];
|
|
}
|
|
|
|
public function testTheFirstPlacementTakesPlaceOne(): void
|
|
{
|
|
$this->assertSame(1, $this->createDisposition(new Assignment(), new Teamer())->getSlot());
|
|
}
|
|
|
|
/**
|
|
* The n8n feed hangs the Wechselpass off the place number: a replacement takes the number the
|
|
* called-off teamer freed, and whoever stays keeps theirs.
|
|
*/
|
|
public function testAReplacementTakesTheFreedPlaceAndTheStayerKeepsTheirs(): void
|
|
{
|
|
$assignment = (new Assignment())->setAvailableDispositions(2);
|
|
$first = $this->createDisposition($assignment, new Teamer());
|
|
$second = $this->createDisposition($assignment, new Teamer());
|
|
|
|
$first->setStatus(Disposition::STATUS_CALLED_OFF);
|
|
$replacement = $this->createDisposition($assignment, new Teamer());
|
|
|
|
$this->assertSame(1, $replacement->getSlot());
|
|
$this->assertSame(2, $second->getSlot());
|
|
$this->assertSame([1 => $replacement, 2 => $second], $assignment->getPlaces());
|
|
}
|
|
|
|
public function testACalledOffPlacementLeavesAnOpenPlace(): void
|
|
{
|
|
$assignment = (new Assignment())->setAvailableDispositions(2);
|
|
$calledOff = $this->createDisposition($assignment, new Teamer());
|
|
$stayer = $this->createDisposition($assignment, new Teamer());
|
|
$calledOff->setStatus(Disposition::STATUS_CALLED_OFF);
|
|
|
|
$this->assertSame([1 => null, 2 => $stayer], $assignment->getPlaces());
|
|
}
|
|
|
|
public function testUnfilledPlacesAreOpen(): void
|
|
{
|
|
$assignment = (new Assignment())->setAvailableDispositions(3);
|
|
$disposition = $this->createDisposition($assignment, new Teamer());
|
|
|
|
$this->assertSame([1 => $disposition, 2 => null, 3 => null], $assignment->getPlaces());
|
|
}
|
|
|
|
/**
|
|
* Striking a place while a high number is still held drops an open low one, not the person.
|
|
*/
|
|
public function testLoweringTheCountKeepsTheHeldPlace(): void
|
|
{
|
|
$assignment = (new Assignment())->setAvailableDispositions(2);
|
|
$calledOff = $this->createDisposition($assignment, new Teamer());
|
|
$stayer = $this->createDisposition($assignment, new Teamer());
|
|
$calledOff->setStatus(Disposition::STATUS_CALLED_OFF);
|
|
|
|
$assignment->setAvailableDispositions(1);
|
|
|
|
$this->assertSame([2 => $stayer], $assignment->getPlaces());
|
|
}
|
|
|
|
public function testAPlaceHeldBeyondTheCountIsStillListed(): void
|
|
{
|
|
$assignment = (new Assignment())->setAvailableDispositions(2);
|
|
$first = $this->createDisposition($assignment, new Teamer());
|
|
$second = $this->createDisposition($assignment, new Teamer());
|
|
|
|
$assignment->setAvailableDispositions(1);
|
|
|
|
$this->assertSame([1 => $first, 2 => $second], $assignment->getPlaces());
|
|
}
|
|
|
|
public function testAnUnnumberedPlacementTakesAFreeNumberAfterTheNumberedOnes(): void
|
|
{
|
|
$assignment = (new Assignment())->setAvailableDispositions(2);
|
|
$unnumbered = $this->createDisposition($assignment, new Teamer())->setSlot(null);
|
|
$numbered = $this->createDisposition($assignment, new Teamer())->setSlot(1);
|
|
|
|
$this->assertSame([1 => $numbered, 2 => $unnumbered], $assignment->getPlaces());
|
|
}
|
|
|
|
private function createDisposition(Assignment $assignment, Teamer $teamer): Disposition
|
|
{
|
|
$disposition = new Disposition(new Application($assignment, $teamer));
|
|
$assignment->addDisposition($disposition);
|
|
|
|
return $disposition;
|
|
}
|
|
}
|