travelDataService = $this->createMock(TravelDataProvider::class); $this->service = new BookingSessionManager($this->travelDataService); } public function testGetOrCreateBookingCreateDtoThrowsWhenSessionMissing(): void { $request = $this->createRequestWithSession(); $this->expectException(BookingSessionNotFoundException::class); $this->service->getOrCreateBookingCreateDto($request); } public function testSaveAndLoadBookingDtoHydratesTravel(): void { $request = $this->createRequestWithSession(); $storedTravel = new Travel(); $storedTravel->id = 12; $storedTravel->hotelId = 34; $bookingDto = new BookingDto($storedTravel, 34); $bookingDto->booking = new Booking(); $bookingDto->booking->travelData = $storedTravel; $hydratedTravel = new Travel(); $hydratedTravel->id = 12; $hydratedTravel->hotelId = 34; $hydratedTravel->label = 'Hydrated travel'; $this->travelDataService ->expects($this->once()) ->method('getTravelData') ->with(12, 34) ->willReturn($hydratedTravel); $this->service->saveBookingDto($request, $bookingDto, BookingDto::MODE_CREATE); $loadedDto = $this->service->getBookingDto($request, BookingDto::MODE_CREATE); $this->assertNotNull($loadedDto); $this->assertSame($hydratedTravel, $loadedDto?->travel); $this->assertSame($hydratedTravel, $loadedDto?->booking?->travelData); } public function testBaselineSnapshotIsCreatedAndReused(): void { $request = $this->createRequestWithSession(); $bookingDto = new BookingDto(new Travel(), 99); $selection = new RoomSelectionDto(); $selection->id = 1; $selection->quantity = 2; $bookingDto->roomSelections = [$selection]; $first = $this->service->getOrCreateBaselineSnapshot($request, $bookingDto); $this->assertSame([[1, 2]], $first); $selection->quantity = 5; $second = $this->service->getOrCreateBaselineSnapshot($request, $bookingDto); $this->assertSame($first, $second); $this->assertSame([[1, 2]], $second); } public function testStoreReturnUrlFallsBackToDefaultForInvalidInput(): void { $request = $this->createRequestWithSession(); $this->service->storeReturnUrl($request, 'javascript:alert(1)'); $this->assertSame(BookingSessionManager::DEFAULT_RETURN_URL, $this->service->getReturnUrl($request)); } public function testClearBookingSessionPreservesReturnUrl(): void { $request = $this->createRequestWithSession(); $this->service->storeReturnUrl($request, 'https://example.test/after-booking'); $this->service->clearBookingSession($request); $this->assertSame('https://example.test/after-booking', $this->service->getReturnUrl($request)); } private function createRequestWithSession(): Request { $session = new Session(new MockArraySessionStorage()); $request = new Request(); $request->setSession($session); return $request; } }