123 lines
4.2 KiB
PHP
123 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Controller\Administrative\System\Destination;
|
|
|
|
use App\BusProNet\DataProvider\HotelDataProvider;
|
|
use App\BusProNet\DataProvider\PickupDataProvider;
|
|
use App\BusProNet\Model\Hotel;
|
|
use App\BusProNet\Model\Pickup;
|
|
use App\Controller\Administrative\System\Destination\DestinationTrait;
|
|
use App\Entity\Destination;
|
|
use App\Model\DestinationDto;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* The shared mapping behind the destination create, edit and duplicate forms.
|
|
*
|
|
* Both behaviours here are about what happens when MyE&P cannot resolve something, which is
|
|
* the state the whole form lands in during an outage: the hotel stops the write, a boarding
|
|
* point does not.
|
|
*/
|
|
class DestinationTraitTest extends TestCase
|
|
{
|
|
/**
|
|
* The same choice App\Command\MyEpImportCommand makes for the export's own unresolvable ids.
|
|
* Dropping the stop would hide a departure the coach actually makes; PickupOptions renders
|
|
* one without a town as "Zustieg {busProId}".
|
|
*/
|
|
public function testAnUnresolvablePickupIsKeptWithoutItsAddress(): void
|
|
{
|
|
$harness = $this->harness($this->hotel(), [4 => $this->pickup()]);
|
|
|
|
$destination = new Destination();
|
|
$harness->map($destination, $this->dto([4, 999]));
|
|
|
|
$this->assertSame([
|
|
['busProId' => 4, 'city' => 'Karlsruhe', 'street' => 'A5 - Autohof Bruchsal', 'time' => null],
|
|
['busProId' => 999, 'city' => null, 'street' => null, 'time' => null],
|
|
], $destination->getPickups());
|
|
}
|
|
|
|
/**
|
|
* ResolvableHotel reports this on the field, and every caller runs behind $form->isValid().
|
|
* This is the second line: a half built destination has no house name, no cost unit and no
|
|
* country, and nothing reads those back until an invoice is stamped.
|
|
*/
|
|
public function testAnUnresolvableHotelRefusesToWriteAnything(): void
|
|
{
|
|
$harness = $this->harness(hotel: null);
|
|
$destination = new Destination();
|
|
|
|
try {
|
|
$harness->map($destination, $this->dto([]));
|
|
$this->fail('Expected a LogicException');
|
|
} catch (\LogicException $e) {
|
|
$this->assertStringContainsString('does not resolve', $e->getMessage());
|
|
}
|
|
|
|
$this->assertNull($destination->getHotel());
|
|
$this->assertNull($destination->getProduct());
|
|
}
|
|
|
|
/**
|
|
* @param ?Hotel $hotel null stands for a hotel the base data cannot resolve
|
|
* @param array<int, Pickup> $pickups keyed by busProId; anything absent does not resolve
|
|
*/
|
|
private function harness(?Hotel $hotel, array $pickups = []): object
|
|
{
|
|
$hotelProvider = $this->createMock(HotelDataProvider::class);
|
|
$hotelProvider->method('get')->willReturn($hotel);
|
|
|
|
$pickupProvider = $this->createMock(PickupDataProvider::class);
|
|
$pickupProvider->method('get')->willReturnCallback(fn ($id) => $pickups[$id] ?? null);
|
|
|
|
return new class($hotelProvider, $pickupProvider) {
|
|
use DestinationTrait;
|
|
|
|
public function __construct(
|
|
private readonly HotelDataProvider $hotelDataProvider,
|
|
private readonly PickupDataProvider $pickupDataProvider,
|
|
) {
|
|
}
|
|
|
|
public function map(Destination $destination, DestinationDto $dto): void
|
|
{
|
|
$this->updateEntity($destination, $dto);
|
|
}
|
|
};
|
|
}
|
|
|
|
private function dto(array $pickupIds): DestinationDto
|
|
{
|
|
return (new DestinationDto())
|
|
->setProduct('Lenzerheide - Sportclub Jenatsch')
|
|
->setDateFrom(new \DateTimeImmutable('2026-04-04'))
|
|
->setDateTo(new \DateTimeImmutable('2026-04-11'))
|
|
->setHotelBusProId('163959')
|
|
->setCountry('ch')
|
|
->setPickups($pickupIds)
|
|
;
|
|
}
|
|
|
|
private function hotel(): Hotel
|
|
{
|
|
return (new Hotel())
|
|
->setBusProId(163959)
|
|
->setCode('LPJGR')
|
|
->setName('Sportclub Jenatsch')
|
|
->setCostUnit('4711')
|
|
;
|
|
}
|
|
|
|
private function pickup(): Pickup
|
|
{
|
|
return (new Pickup())
|
|
->setBusProId(4)
|
|
->setCity('Karlsruhe')
|
|
->setStreet('A5 - Autohof Bruchsal')
|
|
;
|
|
}
|
|
}
|