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 $pickups keyed by busProId; anything absent does not resolve */ private function harness(?Hotel $hotel, array $pickups = []): object { $hotelProvider = $this->createStub(HotelDataProvider::class); $hotelProvider->method('get')->willReturn($hotel); $pickupProvider = $this->createStub(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') ; } }