Files
myep/tests/Form/Model/BookingDtoTest.php
T

293 lines
11 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Form\Model;
use App\BusProNet\Model\Room;
use App\BusProNet\Model\Travel;
use App\BusProNet\Model\Address;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Form\Model\RoomSelectionDto;
use PHPUnit\Framework\TestCase;
/**
* Tests for BookingDto validation and business logic.
*
* Email uniqueness validation tests have been moved to ParticipantEditDtoTest
* as part of the refactoring to use the wrapper DTO pattern.
*/
class BookingDtoTest extends TestCase
{
public function testBookingDtoCanBeInstantiated(): void
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$bookingDto = new BookingDto($travel, 1);
$this->assertInstanceOf(BookingDto::class, $bookingDto);
$this->assertSame($travel, $bookingDto->travel);
$this->assertSame(BookingDto::MODE_CREATE, $bookingDto->getMode());
}
public function testUnserializeHandlesIntTravelId(): void
{
$travel = new Travel();
$travel->id = 42;
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$dto = new BookingDto($travel, 1);
$serialized = serialize($dto);
$restored = unserialize($serialized);
$this->assertInstanceOf(BookingDto::class, $restored);
$this->assertSame(42, $restored->travel->id);
}
public function testUnserializeHandlesLegacyTravelObject(): void
{
$travel = new Travel();
$travel->id = 42;
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
// Simulate old session format where 'travel' is a full Travel object
$data = [
'travel' => $travel,
'hotelId' => 1,
];
$dto = new BookingDto(new Travel(), 1);
$dto->__unserialize($data);
$this->assertSame($travel, $dto->travel);
$this->assertSame(42, $dto->travel->id);
}
public function testUnserializeNormalizesLegacyBodyDimensionsOnParticipants(): void
{
$travel = new Travel();
$travel->id = 42;
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$participant = new ParticipantDto();
$participant->height = '149-157';
$participant->weight = '75';
$participant->shoeSize = '043';
$dto = new BookingDto($travel, 1);
$dto->participants = [$participant];
$restored = unserialize(serialize($dto));
$this->assertInstanceOf(BookingDto::class, $restored);
$this->assertNull($restored->participants[0]->height);
$this->assertSame('75', $restored->participants[0]->weight);
$this->assertSame('43', $restored->participants[0]->shoeSize);
}
public function testSyncRoomSelectionsWithAvailableRoomsClearsMissingOrOverbookedRooms(): void
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$availableRoom = new Room();
$availableRoom->id = 1;
$availableRoom->label = 'Doppelzimmer';
$availableRoom->price = 100.0;
$availableRoom->available = 2;
$availableRoom->minPax = 2;
$availableRoom->status = 'Frei';
$limitedRoom = new Room();
$limitedRoom->id = 2;
$limitedRoom->label = 'Einzelzimmer';
$limitedRoom->price = 150.0;
$limitedRoom->available = 1;
$limitedRoom->minPax = 1;
$limitedRoom->status = 'Frei';
$travel->rooms = [$availableRoom, $limitedRoom];
$dto = new BookingDto($travel, 1);
$selection1 = new RoomSelectionDto();
$selection1->id = 1;
$selection1->quantity = 2;
$selection2 = new RoomSelectionDto();
$selection2->id = 2;
$selection2->quantity = 2;
$selection3 = new RoomSelectionDto();
$selection3->id = 3;
$selection3->quantity = 1;
$dto->roomSelections = [
1 => $selection1,
2 => $selection2,
3 => $selection3,
];
$changed = $dto->syncRoomSelectionsWithAvailableRooms();
$this->assertTrue($changed);
$this->assertCount(2, $dto->roomSelections);
$this->assertArrayHasKey(1, $dto->roomSelections);
$this->assertArrayHasKey(2, $dto->roomSelections);
$this->assertArrayNotHasKey(3, $dto->roomSelections);
$this->assertSame(1, $dto->roomSelections[1]->id);
$this->assertSame(2, $dto->roomSelections[1]->quantity);
$this->assertSame('Doppelzimmer', $dto->roomSelections[1]->label);
$this->assertSame(100.0, $dto->roomSelections[1]->price);
$this->assertSame(2, $dto->roomSelections[1]->maxQuantity);
$this->assertSame(2, $dto->roomSelections[1]->capacity);
$this->assertSame(2, $dto->roomSelections[2]->id);
$this->assertSame(0, $dto->roomSelections[2]->quantity);
}
public function testSyncRoomSelectionsWithAvailableRoomsSynchronizesZeroQuantityRoomMetadata(): void
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$room = new Room();
$room->id = 1;
$room->label = 'Aktualisiertes Zimmer';
$room->price = 125.0;
$room->available = 1;
$room->minPax = 2;
$room->status = 'Anfrage';
$travel->rooms = [$room];
$dto = new BookingDto($travel, 1);
$selection = new RoomSelectionDto();
$selection->id = 1;
$selection->label = 'Veraltetes Zimmer';
$selection->price = 100.0;
$selection->status = 'Frei';
$selection->maxQuantity = 5;
$selection->capacity = 1;
$selection->quantity = 0;
$dto->roomSelections = [1 => $selection];
$changed = $dto->syncRoomSelectionsWithAvailableRooms();
$this->assertFalse($changed);
$this->assertCount(1, $dto->roomSelections);
$this->assertArrayHasKey(1, $dto->roomSelections);
$this->assertSame('Aktualisiertes Zimmer', $dto->roomSelections[1]->label);
$this->assertSame(125.0, $dto->roomSelections[1]->price);
$this->assertSame('Anfrage', $dto->roomSelections[1]->status);
$this->assertSame(1, $dto->roomSelections[1]->maxQuantity);
$this->assertSame(2, $dto->roomSelections[1]->capacity);
$this->assertSame(0, $dto->roomSelections[1]->quantity);
}
public function testSyncRoomSelectionsWithAvailableRoomsAddsNewAvailableRooms(): void
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$room = new Room();
$room->id = 5;
$room->label = 'Familienzimmer';
$room->price = 250.0;
$room->available = 3;
$room->minPax = 4;
$room->status = 'Frei';
$travel->rooms = [$room];
$dto = new BookingDto($travel, 1);
$changed = $dto->syncRoomSelectionsWithAvailableRooms();
$this->assertFalse($changed);
$this->assertArrayHasKey(5, $dto->roomSelections);
$this->assertSame(5, $dto->roomSelections[5]->id);
$this->assertSame('Familienzimmer', $dto->roomSelections[5]->label);
$this->assertSame(250.0, $dto->roomSelections[5]->price);
$this->assertSame('Frei', $dto->roomSelections[5]->status);
$this->assertSame(0, $dto->roomSelections[5]->quantity);
$this->assertSame(3, $dto->roomSelections[5]->maxQuantity);
$this->assertSame(4, $dto->roomSelections[5]->capacity);
}
public function testCreateRoomSelectionSnapshotDetectsPriceOnlyChange(): void
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$dto = new BookingDto($travel, 1);
$selection = new RoomSelectionDto();
$selection->id = 1;
$selection->quantity = 2;
$selection->price = 100.0;
$dto->roomSelections = [$selection];
$before = $dto->createRoomSelectionSnapshot();
$selection->price = 120.0;
$after = $dto->createRoomSelectionSnapshot();
$this->assertSame([[1, 2, 100.0]], $before);
$this->assertSame([[1, 2, 120.0]], $after);
$this->assertNotSame($before, $after);
$this->assertTrue($dto->hasRoomSelectionChanged($before));
}
public function testUnserializeNormalizesLegacyParticipantStringsOnLoad(): void
{
$travel = new Travel();
$travel->id = 42;
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$participant = new ParticipantDto();
$participant->firstName = ' Max ';
$participant->lastName = ' Mustermann ';
$participant->email = ' [email protected] ';
$participant->remarksRoom = ' ';
$participant->licensePlate = ' B-AB 123 ';
$participant->purchaseVoucherCode = ' ABC-123 ';
$participant->promoVoucherCode = ' PROMO ';
$participant->address = new Address();
$participant->address->street = ' Test Street 1 ';
$participant->address->postCode = ' 12345 ';
$participant->address->city = ' Test City ';
$participant->address->country = ' DE ';
$dto = new BookingDto($travel, 1);
$dto->participants = [$participant];
$restored = unserialize(serialize($dto));
$this->assertInstanceOf(BookingDto::class, $restored);
$this->assertSame('Max', $restored->participants[0]->firstName);
$this->assertSame('Mustermann', $restored->participants[0]->lastName);
$this->assertSame('[email protected]', $restored->participants[0]->email);
$this->assertNull($restored->participants[0]->remarksRoom);
$this->assertSame('B-AB 123', $restored->participants[0]->licensePlate);
$this->assertSame('ABC-123', $restored->participants[0]->purchaseVoucherCode);
$this->assertSame('PROMO', $restored->participants[0]->promoVoucherCode);
$this->assertSame('Test Street 1', $restored->participants[0]->address->street);
$this->assertSame('12345', $restored->participants[0]->address->postCode);
$this->assertSame('Test City', $restored->participants[0]->address->city);
$this->assertSame('DE', $restored->participants[0]->address->country);
}
}