Files
myep/tests/Service/BookingServiceBabyTest.php
T
Björn Fromme 776b9d0912 feat: proper determination of agency initiated bookings
For booking that are agency initiated (groups) different rules apply
concerning mutability and requirement of personal data and whether the
first participant is the applicant or not. This commit adds logic to
evaluate the agency id assigned to the booking data to decide.
2026-01-08 12:54:59 +01:00

218 lines
8.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Service;
use App\BusProNet\Constants;
use App\BusProNet\Model\Service;
use App\BusProNet\Model\Travel;
use App\BusProNet\XmlLoader\AgencyLoader;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Service\BookingPriceCalculatorService;
use App\Service\BookingService;
use App\Service\ParticipantEligibilityService;
use App\Service\TravelDataService;
use PHPUnit\Framework\TestCase;
class BookingServiceBabyTest extends TestCase
{
private BookingService $bookingService;
private ParticipantEligibilityService $participantEligibilityService;
protected function setUp(): void
{
$travelDataService = $this->createMock(TravelDataService::class);
$priceCalculator = $this->createMock(BookingPriceCalculatorService::class);
$this->participantEligibilityService = $this->createMock(ParticipantEligibilityService::class);
$agencyLoader = $this->createMock(AgencyLoader::class);
$this->bookingService = new BookingService(
$travelDataService,
$priceCalculator,
$this->participantEligibilityService,
$agencyLoader,
'F' // default booking status
);
}
public function testPreselectMandatoryServicesSkipsBabyParticipant(): void
{
$travel = $this->createTravelWithMandatoryServices();
$bookingDto = new BookingDto($travel, 1);
// Create a baby participant (1 year old at travel date)
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = $travel->dateFrom->modify('-1 year');
$participant->additionalServices = [];
$bookingDto->participants[0] = $participant;
$this->bookingService->preselectMandatoryServices($bookingDto);
$this->assertEmpty($participant->additionalServices, 'Mandatory services should not be preselected for baby participants');
}
public function testPreselectMandatoryServicesSkipsTwoYearOldParticipant(): void
{
$travel = $this->createTravelWithMandatoryServices();
$bookingDto = new BookingDto($travel, 1);
// Create a participant exactly at BABY_MAX_AGE (2 years old at travel date)
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = $travel->dateFrom->modify('-2 years');
$participant->additionalServices = [];
$bookingDto->participants[0] = $participant;
$this->bookingService->preselectMandatoryServices($bookingDto);
$this->assertEmpty($participant->additionalServices, 'Mandatory services should not be preselected for participants at BABY_MAX_AGE');
}
public function testPreselectMandatoryServicesIncludesThreeYearOldParticipant(): void
{
$travel = $this->createTravelWithMandatoryServices();
$bookingDto = new BookingDto($travel, 1);
// Create a participant just over BABY_MAX_AGE (3 years old at travel date)
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = $travel->dateFrom->modify('-3 years');
$participant->additionalServices = [];
$bookingDto->participants[0] = $participant;
// Mock eligibility check - 3-year-old is eligible
$this->participantEligibilityService
->method('isParticipantEligible')
->willReturn(true);
$this->bookingService->preselectMandatoryServices($bookingDto);
$this->assertNotEmpty($participant->additionalServices, 'Mandatory services should be preselected for non-baby participants');
$this->assertCount(1, $participant->additionalServices);
$this->assertSame('Mandatory Service', $participant->additionalServices[0]->label);
}
public function testPreselectMandatoryServicesIncludesAdultParticipant(): void
{
$travel = $this->createTravelWithMandatoryServices();
$bookingDto = new BookingDto($travel, 1);
// Create an adult participant
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = $travel->dateFrom->modify('-25 years');
$participant->additionalServices = [];
$bookingDto->participants[0] = $participant;
// Mock eligibility check - adult is eligible
$this->participantEligibilityService
->method('isParticipantEligible')
->willReturn(true);
$this->bookingService->preselectMandatoryServices($bookingDto);
$this->assertNotEmpty($participant->additionalServices, 'Mandatory services should be preselected for adult participants');
$this->assertCount(1, $participant->additionalServices);
}
public function testPreselectMandatoryServicesHandlesMixedParticipants(): void
{
$travel = $this->createTravelWithMandatoryServices();
$bookingDto = new BookingDto($travel, 1);
// Create a baby participant (index 0)
$babyParticipant = new ParticipantDto();
$babyParticipant->index = 0;
$babyParticipant->dateOfBirth = $travel->dateFrom->modify('-1 year');
$babyParticipant->additionalServices = [];
$bookingDto->participants[0] = $babyParticipant;
// Create an adult participant (index 1)
$adultParticipant = new ParticipantDto();
$adultParticipant->index = 1;
$adultParticipant->dateOfBirth = $travel->dateFrom->modify('-25 years');
$adultParticipant->additionalServices = [];
$bookingDto->participants[1] = $adultParticipant;
// Mock eligibility check - adult is eligible (baby won't be checked)
$this->participantEligibilityService
->method('isParticipantEligible')
->with($bookingDto, 1) // Only called for adult
->willReturn(true);
$this->bookingService->preselectMandatoryServices($bookingDto);
$this->assertEmpty($babyParticipant->additionalServices, 'Baby should not have mandatory services preselected');
$this->assertNotEmpty($adultParticipant->additionalServices, 'Adult should have mandatory services preselected');
}
public function testPreselectMandatoryServicesSkipsNewbornBaby(): void
{
$travel = $this->createTravelWithMandatoryServices();
$bookingDto = new BookingDto($travel, 1);
// Create a newborn (born on travel date)
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = $travel->dateFrom;
$participant->additionalServices = [];
$bookingDto->participants[0] = $participant;
$this->bookingService->preselectMandatoryServices($bookingDto);
$this->assertEmpty($participant->additionalServices, 'Mandatory services should not be preselected for newborn babies');
}
public function testBabyAgeCalculatedAtTravelDate(): void
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('2025-06-01');
$travel->dateTo = new \DateTimeImmutable('2025-06-08');
$travel->additionalServices = $this->createMandatoryAdditionalServices();
$bookingDto = new BookingDto($travel, 1);
// Create a participant who will be 2 at travel date
// Born 2023-06-02 (turns 2 on 2025-06-02), travel date 2025-06-01 = 1 year old at travel start
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = new \DateTimeImmutable('2023-06-02');
$participant->additionalServices = [];
$bookingDto->participants[0] = $participant;
$this->bookingService->preselectMandatoryServices($bookingDto);
// At age 1, participant is a baby and should be skipped
$this->assertEmpty($participant->additionalServices, 'Age should be calculated at travel date, not current date');
}
private function createTravelWithMandatoryServices(): Travel
{
$travel = new Travel();
$travel->dateFrom = new \DateTimeImmutable('+30 days');
$travel->dateTo = new \DateTimeImmutable('+37 days');
$travel->additionalServices = $this->createMandatoryAdditionalServices();
return $travel;
}
/**
* @return array<int, Service>
*/
private function createMandatoryAdditionalServices(): array
{
$mandatoryService = new Service();
$mandatoryService->id = 1;
$mandatoryService->label = 'Mandatory Service';
$mandatoryService->subType = Constants::TOKEN_ADDITIONAL;
$mandatoryService->mandatory = true;
$mandatoryService->available = 10;
$mandatoryService->price = 10.0;
return [1 => $mandatoryService];
}
}