171 lines
6.5 KiB
PHP
171 lines
6.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Service;
|
|
|
|
use App\BusProNet\Model\Insurance;
|
|
use App\BusProNet\Model\Travel;
|
|
use App\Form\Model\BookingDto;
|
|
use App\Form\Model\ParticipantDto;
|
|
use App\Service\BookingPriceCalculator;
|
|
use App\Service\FamilyInsuranceAvailabilityChecker;
|
|
use App\Service\InsuranceManager;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class FamilyInsuranceAvailabilityCheckerTest extends TestCase
|
|
{
|
|
private FamilyInsuranceAvailabilityChecker $checker;
|
|
private InsuranceManager $insuranceService;
|
|
private BookingPriceCalculator $priceCalculatorService;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->insuranceService = $this->createStub(InsuranceManager::class);
|
|
$this->priceCalculatorService = $this->createStub(BookingPriceCalculator::class);
|
|
|
|
$this->insuranceService->method('getSelectableInsurances')
|
|
->willReturnCallback(fn (Travel $travel) => $travel->insurances ?? []);
|
|
|
|
$this->priceCalculatorService->method('calculateTotalBookingPriceExcludingInsurance')
|
|
->willReturn(500.0);
|
|
|
|
$this->checker = new FamilyInsuranceAvailabilityChecker($this->insuranceService, $this->priceCalculatorService);
|
|
}
|
|
|
|
public function testUpgradeIsAvailableWhenFamilyBecameEligibleAfterTheApplicantChose(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertTrue($this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto));
|
|
}
|
|
|
|
public function testUpgradeIsNotAvailableWhenTheApplicantChoseWhileFamilyWasAlreadyEligible(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
$bookingDto->applicantInsuranceChosenWhileFamilyIneligible = false;
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertFalse(
|
|
$this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto),
|
|
'An applicant who was offered family insurance and picked something else must not be nagged'
|
|
);
|
|
}
|
|
|
|
public function testUpgradeIsNotAvailableWhenApplicantHasNoInsuranceYet(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
$bookingDto->getParticipant(0)->insurance = null;
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertFalse($this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto));
|
|
}
|
|
|
|
public function testUpgradeIsNotAvailableWhenApplicantAlreadyHasFamilyInsurance(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
$familyInsurance = $this->createInsurance('2');
|
|
$familyInsurance->familyInsurance = true;
|
|
$bookingDto->getParticipant(0)->insurance = $familyInsurance;
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertFalse($this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto));
|
|
}
|
|
|
|
public function testUpgradeIsNotAvailableWhenNoFamilyInsuranceProductExists(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
$bookingDto->travel->insurances = array_values(array_filter(
|
|
$bookingDto->travel->insurances,
|
|
static fn (Insurance $i) => false === $i->familyInsurance
|
|
));
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertFalse($this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto));
|
|
}
|
|
|
|
public function testUpgradeIsNotAvailableWhenNoFamilyPriceTierMatches(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
|
|
// Family composition qualifies, but no family insurance matches the total price
|
|
$this->insuranceService->method('getEligibleInsurances')->willReturn([]);
|
|
|
|
$this->assertFalse($this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto));
|
|
}
|
|
|
|
public function testUpgradeIsNotAvailableWhenTheBookingIsNotAFamilyBooking(): void
|
|
{
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
// Dependent is an adult - no children left, so the constellation no longer qualifies
|
|
$bookingDto->getParticipant(1)->dateOfBirth = new \DateTimeImmutable('1992-01-01');
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertFalse($this->checker->isFamilyInsuranceUpgradeAvailable($bookingDto));
|
|
}
|
|
|
|
public function testHasEligibleFamilyInsuranceIgnoresTheSelectionTimeRecording(): void
|
|
{
|
|
// The raw availability predicate is what the field handler records against, so it
|
|
// must not itself depend on the flag it is used to compute
|
|
$bookingDto = $this->createFamilyBookingDtoWithNonFamilyApplicantInsurance();
|
|
$bookingDto->applicantInsuranceChosenWhileFamilyIneligible = false;
|
|
|
|
$this->allowAllInsurancesAsEligible();
|
|
|
|
$this->assertTrue($this->checker->hasEligibleFamilyInsurance($bookingDto));
|
|
}
|
|
|
|
private function allowAllInsurancesAsEligible(): void
|
|
{
|
|
$this->insuranceService->method('getEligibleInsurances')->willReturnCallback(
|
|
fn (array $insurances) => $insurances
|
|
);
|
|
}
|
|
|
|
private function createFamilyBookingDtoWithNonFamilyApplicantInsurance(): BookingDto
|
|
{
|
|
$nonFamilyInsurance = $this->createInsurance('1');
|
|
$nonFamilyInsurance->familyInsurance = false;
|
|
|
|
$familyInsurance = $this->createInsurance('2', 'Reise-Rücktritt Familie');
|
|
$familyInsurance->familyInsurance = true;
|
|
|
|
$travel = new Travel();
|
|
$travel->dateFrom = new \DateTimeImmutable('2025-08-01');
|
|
$travel->dateTo = new \DateTimeImmutable('2025-08-08');
|
|
$travel->insurances = [$nonFamilyInsurance, $familyInsurance];
|
|
|
|
$applicant = new ParticipantDto();
|
|
$applicant->index = 0;
|
|
$applicant->dateOfBirth = new \DateTimeImmutable('1990-06-15');
|
|
$applicant->insurance = $nonFamilyInsurance;
|
|
|
|
$child = new ParticipantDto();
|
|
$child->index = 1;
|
|
$child->dateOfBirth = new \DateTimeImmutable('2015-01-01');
|
|
|
|
$bookingDto = new BookingDto($travel, 1);
|
|
$bookingDto->participants = [$applicant, $child];
|
|
$bookingDto->applicantInsuranceChosenWhileFamilyIneligible = true;
|
|
|
|
return $bookingDto;
|
|
}
|
|
|
|
private function createInsurance(string|int $id, string $label = 'Test Insurance'): Insurance
|
|
{
|
|
$insurance = new Insurance();
|
|
$insurance->id = (string) $id;
|
|
$insurance->label = $label;
|
|
|
|
return $insurance;
|
|
}
|
|
}
|