fix: always filter ski passes by participant's age

This commit is contained in:
Björn Fromme
2026-05-07 11:40:45 +02:00
parent 8ac62d2a02
commit eaff989bdd
2 changed files with 142 additions and 14 deletions
@@ -5,8 +5,10 @@ declare(strict_types=1);
namespace App\Tests\Form\Service;
use App\BusProNet\Constants;
use App\BusProNet\Model\Booking;
use App\BusProNet\Model\Service;
use App\BusProNet\Model\Travel;
use App\BusProNet\XmlParser\TravelParser;
use App\BusProNet\Utility\DirectionMapper;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
@@ -16,6 +18,7 @@ use App\Service\InsuranceManager;
use App\Service\ServiceAvailabilityCalculator;
use App\Service\ServiceLabelFormatter;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Contracts\Translation\TranslatorInterface;
class ParticipantFieldOptionsProviderBabyTest extends TestCase
@@ -30,6 +33,45 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$priceCalculatorService = $this->createMock(BookingPriceCalculator::class);
$serviceLabelFormatter = new ServiceLabelFormatter();
$translator = $this->createMock(TranslatorInterface::class);
$translator->method('trans')->willReturnCallback(
function (string $message, array $parameters = []): string {
return match ($message) {
'service.age_constraint.prefix' => sprintf('Nur %s', $parameters['%constraint%'] ?? ''),
'service.age_constraint.absolute_age.range' => sprintf(
'Alter %s-%s',
$parameters['%ageFrom%'] ?? '',
$parameters['%ageTo%'] ?? ''
),
'service.age_constraint.absolute_age.min' => sprintf(
'Alter ab %s',
$parameters['%ageFrom%'] ?? ''
),
'service.age_constraint.absolute_age.max' => sprintf(
'Alter bis %s',
$parameters['%ageTo%'] ?? ''
),
'service.age_constraint.birth_year.single' => sprintf(
'Jahrgang %s',
$parameters['%year%'] ?? ''
),
'service.age_constraint.birth_year.range' => sprintf(
'Jahrgang %s-%s',
$parameters['%yearFrom%'] ?? '',
$parameters['%yearTo%'] ?? ''
),
'service.age_constraint.birth_year.min' => sprintf(
'Jahrgang ab %s',
$parameters['%yearFrom%'] ?? ''
),
'service.age_constraint.birth_year.max' => sprintf(
'Jahrgang bis %s',
$parameters['%yearTo%'] ?? ''
),
'service.age_constraint.mixed.separator' => ' und ',
default => $message,
};
}
);
$this->provider = new ParticipantFieldOptionsProvider(
$this->serviceAvailabilityCalculator,
@@ -128,6 +170,75 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$this->assertContains(3, $choiceIds, 'Service without age restrictions should be shown for adult');
}
public function testSkiPassesAreFilteredByBirthYearForAdultParticipant(): void
{
$travel = $this->createTravelWithExportedSkiPasses([195992, 195984]);
$bookingDto = new BookingDto($travel, 1);
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = new \DateTimeImmutable('1990-12-26');
$bookingDto->participants[0] = $participant;
$options = $this->provider->getFieldOptions('skiPass', $bookingDto, 0);
$this->assertEmpty($options, 'Adult participant should not see birth-year-mismatched ski passes');
}
public function testSkiPassesKeepMatchingBirthYearAndHideMismatchedPasses(): void
{
$travel = $this->createTravelWithExportedSkiPasses([195992, 195984]);
$bookingDto = new BookingDto($travel, 1);
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = new \DateTimeImmutable('2011-12-26');
$bookingDto->participants[0] = $participant;
$options = $this->provider->getFieldOptions('skiPass', $bookingDto, 0);
$choices = $options['choices'];
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
$this->assertContains(195992, $choiceIds, 'Matching 2009-2012 ski pass should remain visible');
$this->assertNotContains(195984, $choiceIds, '2013-2020 ski pass should be hidden for a 2011-born participant');
}
public function testEditModePreservesBookedSkiPassEvenWhenBirthYearMismatched(): void
{
$travel = $this->createTravelWithExportedSkiPasses([195992, 195984]);
$bookingDto = new BookingDto($travel, 1);
$bookedSkiPass = clone $travel->additionalServices[195992];
$bookedSkiPass->mapping = [0];
$booking = new Booking();
$booking->additionalServices = [
195992 => $bookedSkiPass,
];
$bookingDto->booking = $booking;
$participant = new ParticipantDto();
$participant->index = 0;
$participant->dateOfBirth = new \DateTimeImmutable('1990-12-26');
$participant->skiPass = $bookedSkiPass;
$bookingDto->participants[0] = $participant;
$options = $this->provider->getFieldOptions('skiPass', $bookingDto, 0);
$choices = $options['choices'];
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
$this->assertContains(195992, $choiceIds, 'Booked ski pass should remain visible in edit mode');
$choiceAttr = $options['choice_attr'];
$attributes = $choiceAttr($choices[195992] ?? $choices[array_key_first($choices)]);
$this->assertTrue($attributes['readonly']);
$this->assertArrayHasKey('data-tooltip', $attributes);
$this->assertStringContainsString('2009', $attributes['data-tooltip']);
}
public function testBabyGetRegularPkwInTransportation(): void
{
$travel = $this->createTravelWithTransportation();
@@ -364,4 +475,22 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
return $travel;
}
/**
* @param list<int> $serviceIds
*/
private function createTravelWithExportedSkiPasses(array $serviceIds): Travel
{
$parser = new TravelParser();
$crawler = new Crawler(file_get_contents('/var/www/html/var/xmlexport/Ziel_2456.xml'));
$travelNode = $crawler->filterXPath('//reise/termin')->first();
$travel = $parser->parse($travelNode);
$travel->additionalServices = array_intersect_key(
$travel->additionalServices,
array_flip($serviceIds)
);
return $travel;
}
}