feat: selectable drop-offs for inbound bus travel

This commit is contained in:
Björn Fromme
2026-03-16 12:03:00 +01:00
parent f8a56b7de2
commit f795a3ea21
31 changed files with 701 additions and 200 deletions
@@ -423,7 +423,7 @@ class BookingDataProcessorTest extends TestCase
private function createFormDataWithoutPickups(): BookingDto
{
$formData = $this->createCompleteFormData();
$formData->booking->pickupsOutbound = [];
$formData->booking->pickups = [];
return $formData;
}
@@ -441,8 +441,8 @@ class BookingDataProcessorTest extends TestCase
$booking->paymentType = 'CC';
$booking->additionalServices = [];
$booking->transportationServices = [];
$booking->pickupsOutbound = [];
$booking->pickupsInbound = [];
$booking->pickups = [];
$booking->dropOffs = [];
$booking->participants = [
$this->createMockPersonalData('Participant0'),
$this->createMockPersonalData('Participant1'),
@@ -603,8 +603,8 @@ class BookingDataProcessorTest extends TestCase
$booking->paymentType = 'CC';
$booking->additionalServices = [];
$booking->transportationServices = [];
$booking->pickupsOutbound = [];
$booking->pickupsInbound = [];
$booking->pickups = [];
$booking->dropOffs = [];
$canceledParticipant = new PersonalData();
$canceledParticipant->firstName = '';
@@ -0,0 +1,242 @@
<?php
declare(strict_types=1);
namespace App\Tests\Form\Service;
use App\BusProNet\Model\Pickup;
use App\BusProNet\Model\Service;
use App\BusProNet\Model\Travel;
use App\BusProNet\Utility\DirectionMapper;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Form\Service\ParticipantDropOffFieldHandler;
use PHPUnit\Framework\TestCase;
class ParticipantDropOffFieldHandlerTest extends TestCase
{
private ParticipantDropOffFieldHandler $handler;
protected function setUp(): void
{
$this->handler = new ParticipantDropOffFieldHandler();
}
public function testGetFieldName(): void
{
$this->assertSame('dropOff', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$this->assertSame(
['transportationOutbound', 'transportationInbound', 'pickup'],
$this->handler->getDependencies()
);
}
public function testShouldProcessAlwaysReturnsTrue(): void
{
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
}
public function testProcessFieldWithoutParticipant(): void
{
$travel = new Travel();
$bookingDto = new BookingDto($travel, 1);
$submittedData = ['dropOff' => '10'];
$this->handler->processField($submittedData, $bookingDto, 0);
$this->expectNotToPerformAssertions();
}
public function testBusBusCheckboxCheckedValidSelection(): void
{
$dropOff = $this->createDropOff(10, 'Berlin Hbf');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_BUS_API,
DirectionMapper::SUBTYPE_BUS_API,
[$dropOff]
);
$submittedData = [
'differentDropOff' => '1',
'dropOff' => '10',
];
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNotNull($participant->dropOff);
$this->assertSame(10, $participant->dropOff->id);
$this->assertTrue($participant->differentDropOff);
}
public function testBusBusCheckboxUncheckedClearsDropOff(): void
{
$dropOff = $this->createDropOff(10, 'Berlin Hbf');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_BUS_API,
DirectionMapper::SUBTYPE_BUS_API,
[$dropOff]
);
$participant = $bookingDto->getParticipant(0);
$participant->dropOff = $dropOff;
$participant->differentDropOff = true;
$submittedData = [
'differentDropOff' => false,
'dropOff' => '10',
];
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
}
public function testPkwBusValidSelection(): void
{
$dropOff = $this->createDropOff(20, 'München ZOB');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_CAR_API,
DirectionMapper::SUBTYPE_BUS_API,
[$dropOff]
);
$submittedData = [
'dropOff' => '20',
];
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNotNull($participant->dropOff);
$this->assertSame(20, $participant->dropOff->id);
$this->assertFalse($participant->differentDropOff);
}
public function testBusPkwClearsDropOff(): void
{
$dropOff = $this->createDropOff(10, 'Berlin Hbf');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_BUS_API,
DirectionMapper::SUBTYPE_CAR_API,
[$dropOff]
);
$participant = $bookingDto->getParticipant(0);
$participant->dropOff = $dropOff;
$participant->differentDropOff = true;
$submittedData = ['dropOff' => '10'];
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
}
public function testPkwPkwClearsDropOff(): void
{
$dropOff = $this->createDropOff(10, 'Berlin Hbf');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_CAR_API,
DirectionMapper::SUBTYPE_CAR_API,
[$dropOff]
);
$participant = $bookingDto->getParticipant(0);
$participant->dropOff = $dropOff;
$submittedData = ['dropOff' => '10'];
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
}
public function testInvalidDropOffIdSetsNull(): void
{
$dropOff = $this->createDropOff(10, 'Berlin Hbf');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_CAR_API,
DirectionMapper::SUBTYPE_BUS_API,
[$dropOff]
);
$submittedData = [
'dropOff' => '999',
];
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNull($participant->dropOff);
}
public function testBusBusCheckboxCheckedNoSelection(): void
{
$dropOff = $this->createDropOff(10, 'Berlin Hbf');
$bookingDto = $this->createBookingDto(
DirectionMapper::SUBTYPE_BUS_API,
DirectionMapper::SUBTYPE_BUS_API,
[$dropOff]
);
$submittedData = [
'differentDropOff' => '1',
];
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNull($participant->dropOff);
$this->assertTrue($participant->differentDropOff);
}
private function createDropOff(int $id, string $label): Pickup
{
$pickup = new Pickup();
$pickup->id = $id;
$pickup->city = $label;
$pickup->price = 5.0;
return $pickup;
}
private function createTransportationService(string $subType): Service
{
$service = new Service();
$service->id = random_int(100, 999);
$service->label = 'Transport '.$subType;
$service->subType = $subType;
return $service;
}
/**
* @param Pickup[] $dropOffs
*/
private function createBookingDto(string $outboundSubType, string $inboundSubType, array $dropOffs): BookingDto
{
$travel = new Travel();
foreach ($dropOffs as $dropOff) {
$travel->dropOffs[$dropOff->id] = $dropOff;
}
$participant = new ParticipantDto();
$participant->index = 0;
$participant->transportationOutbound = $this->createTransportationService($outboundSubType);
$participant->transportationInbound = $this->createTransportationService($inboundSubType);
$bookingDto = new BookingDto($travel, 1);
$bookingDto->participants = [$participant];
return $bookingDto;
}
}