chore: major code cleanup and type safety using phpstan

This commit is contained in:
Björn Fromme committed 2026-04-16 17:11:16 +02:00
1 parent 060cbea9da
commit 3da73d626b
103 files changed
+976 -1192

No files matched your search

@@ -38,7 +38,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertFalse($result, 'Insurance should always be editable in create flow');
self::assertFalse($result, 'Insurance should always be editable in create flow');
}
public function testReadonlyWhen40DaysBeforeTravel(): void
@@ -51,7 +51,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
self::assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
}
public function testReadonlyWhenExactly30DaysBeforeTravel(): void
@@ -65,7 +65,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
self::assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
}
public function testReadonlyWhen20DaysBeforeTravel(): void
@@ -78,7 +78,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly when 20 days before travel (standard case)');
self::assertTrue($result, 'Insurance should be readonly when 20 days before travel (standard case)');
}
public function testReadonlyWhen2DaysAfterLateBooking(): void
@@ -92,7 +92,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
self::assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
}
public function testReadonlyWhenExactly3DaysAfterLateBooking(): void
@@ -106,7 +106,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
self::assertTrue($result, 'Insurance should be readonly in edit mode (API limitation)');
}
public function testReadonlyWhen5DaysAfterLateBooking(): void
@@ -120,7 +120,7 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly 5 days after late booking');
self::assertTrue($result, 'Insurance should be readonly 5 days after late booking');
}
public function testReadonlyWhenTravelDatePassed(): void
@@ -133,24 +133,24 @@ class InsuranceMutabilityConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Insurance should be readonly when travel date has passed');
self::assertTrue($result, 'Insurance should be readonly when travel date has passed');
}
public function testGetDependentFieldsReturnsEmptyArray(): void
{
$result = $this->condition->getDependentFields();
$this->assertIsArray($result);
$this->assertEmpty($result, 'Insurance mutability has no field dependencies');
self::assertIsArray($result);
self::assertEmpty($result, 'Insurance mutability has no field dependencies');
}
public function testGetDescriptionReturnsString(): void
{
$result = $this->condition->getDescription();
$this->assertIsString($result);
$this->assertStringContainsString('not editable', $result);
$this->assertStringContainsString('edit mode', $result);
self::assertIsString($result);
self::assertStringContainsString('not editable', $result);
self::assertStringContainsString('edit mode', $result);
}
private function createEditDto(\DateTimeImmutable $travelDate, \DateTimeImmutable $bookingDate): BookingDto
@@ -25,7 +25,7 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertFalse($result, 'Condition should return false when no rooms are selected');
self::assertFalse($result, 'Condition should return false when no rooms are selected');
}
public function testReturnsTrueWhenExactlyOneRoomSelected(): void
@@ -36,7 +36,7 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Condition should return true when exactly one room type is selected');
self::assertTrue($result, 'Condition should return true when exactly one room type is selected');
}
public function testReturnsFalseWhenTwoRoomsSelected(): void
@@ -48,7 +48,7 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertFalse($result, 'Condition should return false when two room types are selected');
self::assertFalse($result, 'Condition should return false when two room types are selected');
}
public function testReturnsFalseWhenMultipleRoomsSelected(): void
@@ -61,7 +61,7 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertFalse($result, 'Condition should return false when multiple room types are selected');
self::assertFalse($result, 'Condition should return false when multiple room types are selected');
}
public function testIgnoresRoomsWithZeroQuantity(): void
@@ -74,7 +74,7 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Condition should ignore rooms with zero quantity');
self::assertTrue($result, 'Condition should ignore rooms with zero quantity');
}
public function testIgnoresRoomsWithNullQuantity(): void
@@ -86,7 +86,7 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertTrue($result, 'Condition should ignore rooms with null quantity');
self::assertTrue($result, 'Condition should ignore rooms with null quantity');
}
public function testReturnsFalseWhenAllRoomsHaveZeroQuantity(): void
@@ -98,24 +98,24 @@ class SingleRoomTypeConditionTest extends TestCase
$result = $this->condition->evaluate($bookingDto, 0, []);
$this->assertFalse($result, 'Condition should return false when all rooms have zero quantity');
self::assertFalse($result, 'Condition should return false when all rooms have zero quantity');
}
public function testGetDependentFieldsReturnsEmptyArray(): void
{
$result = $this->condition->getDependentFields();
$this->assertIsArray($result);
$this->assertEmpty($result, 'Single room type condition has no participant-level field dependencies');
self::assertIsArray($result);
self::assertEmpty($result, 'Single room type condition has no participant-level field dependencies');
}
public function testGetDescriptionReturnsString(): void
{
$result = $this->condition->getDescription();
$this->assertIsString($result);
$this->assertStringContainsString('readonly', $result);
$this->assertStringContainsString('one room type', $result);
self::assertIsString($result);
self::assertStringContainsString('readonly', $result);
self::assertStringContainsString('one room type', $result);
}
/**
@@ -22,24 +22,24 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
public function testGetFieldName(): void
{
$this->assertSame('assignedRoomId', $this->handler->getFieldName());
self::assertSame('assignedRoomId', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$this->assertSame([], $this->handler->getDependencies());
self::assertSame([], $this->handler->getDependencies());
}
public function testShouldProcessReturnsTrueWhenFieldPresent(): void
{
$this->assertTrue($this->handler->shouldProcess(['assignedRoomId' => '1'], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['assignedRoomId' => ''], BookingDto::MODE_EDIT, 5));
self::assertTrue($this->handler->shouldProcess(['assignedRoomId' => '1'], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess(['assignedRoomId' => ''], BookingDto::MODE_EDIT, 5));
}
public function testShouldProcessReturnsFalseWhenFieldNotPresent(): void
{
$this->assertFalse($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertFalse($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
self::assertFalse($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
self::assertFalse($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
}
public function testProcessFieldWithoutParticipant(): void
@@ -67,7 +67,7 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertSame(1, $participant->assignedRoomId);
self::assertSame(1, $participant->assignedRoomId);
}
public function testProcessFieldUnassignsParticipantWhenRoomIdIsEmpty(): void
@@ -83,7 +83,7 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->assignedRoomId);
self::assertNull($participant->assignedRoomId);
}
public function testProcessFieldUnassignsParticipantWhenRoomIdIsNull(): void
@@ -99,7 +99,7 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->assignedRoomId);
self::assertNull($participant->assignedRoomId);
}
public function testProcessFieldUnassignsHighestIndexParticipantWhenRoomAtCapacity(): void
@@ -125,9 +125,9 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 2);
// Participant 1 (highest index with room 1) should be unassigned
$this->assertSame(1, $participant0->assignedRoomId); // Still assigned (applicant protection)
$this->assertNull($participant1->assignedRoomId); // Unassigned
$this->assertSame(1, $participant2->assignedRoomId); // Newly assigned
self::assertSame(1, $participant0->assignedRoomId); // Still assigned (applicant protection)
self::assertNull($participant1->assignedRoomId); // Unassigned
self::assertSame(1, $participant2->assignedRoomId); // Newly assigned
}
public function testProcessFieldGeneratesWarningNotificationForUnassignedParticipant(): void
@@ -151,13 +151,13 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
// Participant 1 should have a warning notification
$notifications = $participant1->notifications;
$this->assertCount(1, $notifications);
self::assertCount(1, $notifications);
// Get first notification (notifications are keyed by hash, not numeric index)
$firstNotification = reset($notifications);
$this->assertSame('warning', $firstNotification['type']);
$this->assertStringContainsString('Doppelzimmer', $firstNotification['message']);
$this->assertStringContainsString('wurde von', $firstNotification['message']);
$this->assertStringContainsString('entfernt', $firstNotification['message']);
self::assertSame('warning', $firstNotification['type']);
self::assertStringContainsString('Doppelzimmer', $firstNotification['message']);
self::assertStringContainsString('wurde von', $firstNotification['message']);
self::assertStringContainsString('entfernt', $firstNotification['message']);
}
public function testProcessFieldDoesNotGenerateNotificationForAssignedParticipant(): void
@@ -180,7 +180,7 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 2);
// Participant 2 (the one being assigned) should NOT have a notification (user-initiated action)
$this->assertEmpty($participant2->notifications);
self::assertEmpty($participant2->notifications);
}
public function testProcessFieldHandlesRoomChangeWithoutConflict(): void
@@ -203,9 +203,9 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
// Both should remain assigned (participant 0's own slot was freed, so no conflict)
$this->assertSame(1, $participant0->assignedRoomId);
$this->assertSame(1, $participant1->assignedRoomId);
$this->assertEmpty($participant1->notifications);
self::assertSame(1, $participant0->assignedRoomId);
self::assertSame(1, $participant1->assignedRoomId);
self::assertEmpty($participant1->notifications);
}
public function testProcessFieldUnassignsMultipleParticipantsWhenNeeded(): void
@@ -234,10 +234,10 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
// All three participants with room 1 should be unassigned (highest indices first: 2, 1, 0)
// But we only need to unassign enough to make space (3 participants, only 1 space needed)
$this->assertNull($participant2->assignedRoomId); // Highest index, unassigned first
$this->assertNull($participant1->assignedRoomId); // Second highest, unassigned second
$this->assertNull($participant0->assignedRoomId); // Third highest, unassigned third
$this->assertSame(1, $participant3->assignedRoomId); // Newly assigned
self::assertNull($participant2->assignedRoomId); // Highest index, unassigned first
self::assertNull($participant1->assignedRoomId); // Second highest, unassigned second
self::assertNull($participant0->assignedRoomId); // Third highest, unassigned third
self::assertSame(1, $participant3->assignedRoomId); // Newly assigned
}
public function testProcessFieldHandlesNoConflictWithMultipleRoomQuantities(): void
@@ -265,13 +265,13 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 3);
// All should remain assigned (4 beds available, 4 participants)
$this->assertSame(1, $participant0->assignedRoomId);
$this->assertSame(1, $participant1->assignedRoomId);
$this->assertSame(1, $participant2->assignedRoomId);
$this->assertSame(1, $participant3->assignedRoomId);
$this->assertEmpty($participant0->notifications);
$this->assertEmpty($participant1->notifications);
$this->assertEmpty($participant2->notifications);
self::assertSame(1, $participant0->assignedRoomId);
self::assertSame(1, $participant1->assignedRoomId);
self::assertSame(1, $participant2->assignedRoomId);
self::assertSame(1, $participant3->assignedRoomId);
self::assertEmpty($participant0->notifications);
self::assertEmpty($participant1->notifications);
self::assertEmpty($participant2->notifications);
}
public function testProcessFieldHandlesComplexScenarioWithMultipleRoomTypes(): void
@@ -301,10 +301,10 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 3);
// Participant 1 (highest index with room 1) should be unassigned
$this->assertSame(1, $participant0->assignedRoomId);
$this->assertNull($participant1->assignedRoomId); // Unassigned
$this->assertSame(2, $participant2->assignedRoomId); // Still in Einzelzimmer
$this->assertSame(1, $participant3->assignedRoomId); // Newly assigned to Doppelzimmer
self::assertSame(1, $participant0->assignedRoomId);
self::assertNull($participant1->assignedRoomId); // Unassigned
self::assertSame(2, $participant2->assignedRoomId); // Still in Einzelzimmer
self::assertSame(1, $participant3->assignedRoomId); // Newly assigned to Doppelzimmer
}
public function testProcessFieldHandlesEdgeCaseWhenRoomNotFoundInSelections(): void
@@ -322,7 +322,7 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
// Should still assign (no conflict detection possible, but assignment proceeds)
$this->assertSame(999, $participant->assignedRoomId);
self::assertSame(999, $participant->assignedRoomId);
}
/**
@@ -24,12 +24,12 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
public function testGetFieldName(): void
{
$this->assertSame('dropOff', $this->handler->getFieldName());
self::assertSame('dropOff', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$this->assertSame(
self::assertSame(
['transportationOutbound', 'transportationInbound', 'pickup'],
$this->handler->getDependencies()
);
@@ -37,8 +37,8 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
public function testShouldProcessAlwaysReturnsTrue(): void
{
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
self::assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
}
public function testProcessFieldWithoutParticipant(): void
@@ -69,9 +69,9 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNotNull($participant->dropOff);
$this->assertSame(10, $participant->dropOff->id);
$this->assertTrue($participant->differentDropOff);
self::assertNotNull($participant->dropOff);
self::assertSame(10, $participant->dropOff->id);
self::assertTrue($participant->differentDropOff);
}
public function testBusBusCheckboxUncheckedAssignsMatchingDropOff(): void
@@ -98,9 +98,9 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNotNull($participant->dropOff);
$this->assertSame(10, $participant->dropOff->id);
$this->assertFalse($participant->differentDropOff);
self::assertNotNull($participant->dropOff);
self::assertSame(10, $participant->dropOff->id);
self::assertFalse($participant->differentDropOff);
}
public function testBusBusCheckboxUncheckedNoPickupKeepsDropOffNull(): void
@@ -121,8 +121,8 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
self::assertNull($participant->dropOff);
self::assertFalse($participant->differentDropOff);
}
public function testBusBusCheckboxUncheckedPickupWithNoMatchingDropOff(): void
@@ -147,8 +147,8 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
self::assertNull($participant->dropOff);
self::assertFalse($participant->differentDropOff);
}
public function testPkwBusValidSelection(): void
@@ -167,9 +167,9 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNotNull($participant->dropOff);
$this->assertSame(20, $participant->dropOff->id);
$this->assertFalse($participant->differentDropOff);
self::assertNotNull($participant->dropOff);
self::assertSame(20, $participant->dropOff->id);
self::assertFalse($participant->differentDropOff);
}
public function testBusPkwClearsDropOff(): void
@@ -189,8 +189,8 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
self::assertNull($participant->dropOff);
self::assertFalse($participant->differentDropOff);
}
public function testPkwPkwClearsDropOff(): void
@@ -209,8 +209,8 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->dropOff);
$this->assertFalse($participant->differentDropOff);
self::assertNull($participant->dropOff);
self::assertFalse($participant->differentDropOff);
}
public function testInvalidDropOffIdSetsNull(): void
@@ -229,7 +229,7 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNull($participant->dropOff);
self::assertNull($participant->dropOff);
}
public function testBusBusCheckboxCheckedNoSelection(): void
@@ -248,8 +248,8 @@ class ParticipantDropOffFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$participant = $bookingDto->getParticipant(0);
$this->assertNull($participant->dropOff);
$this->assertTrue($participant->differentDropOff);
self::assertNull($participant->dropOff);
self::assertTrue($participant->differentDropOff);
}
private function createDropOff(int $id, string $label): Pickup
@@ -15,13 +15,15 @@ use App\Service\BookingPriceCalculator;
use App\Service\InsuranceManager;
use App\Service\ServiceLabelFormatter;
use App\Service\ServiceAvailabilityCalculator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Contracts\Translation\TranslatorInterface;
class ParticipantFieldOptionsProviderBabyTest extends TestCase
{
private ParticipantFieldOptionsProvider $provider;
private ServiceAvailabilityCalculator $serviceAvailabilityCalculator;
/** @var ServiceAvailabilityCalculator&MockObject */
private $serviceAvailabilityCalculator;
protected function setUp(): void
{
@@ -57,9 +59,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// Baby should see only service with age range 0-14 that includes them
$this->assertContains(1, $choiceIds, 'Service with age range 0-14 should be shown for baby');
$this->assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for baby (age < 6)');
$this->assertNotContains(3, $choiceIds, 'Service without age restrictions should be hidden for baby');
self::assertContains(1, $choiceIds, 'Service with age range 0-14 should be shown for baby');
self::assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for baby (age < 6)');
self::assertNotContains(3, $choiceIds, 'Service without age restrictions should be hidden for baby');
}
public function testTwoYearOldOnlySeesServicesWithExplicitAgeRange(): void
@@ -79,9 +81,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// 2-year-old should see only service with age range that includes them
$this->assertContains(1, $choiceIds, 'Service with age range 0-14 should be shown for 2-year-old');
$this->assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for 2-year-old');
$this->assertNotContains(3, $choiceIds, 'Service without age restrictions should be hidden for 2-year-old');
self::assertContains(1, $choiceIds, 'Service with age range 0-14 should be shown for 2-year-old');
self::assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for 2-year-old');
self::assertNotContains(3, $choiceIds, 'Service without age restrictions should be hidden for 2-year-old');
}
public function testThreeYearOldSeesAllApplicableServices(): void
@@ -101,9 +103,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// 3-year-old is not a baby, should see service with age range that includes them AND no-restriction services
$this->assertContains(1, $choiceIds, 'Service with age range 0-14 should be shown for 3-year-old');
$this->assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for 3-year-old (age < 6)');
$this->assertContains(3, $choiceIds, 'Service without age restrictions should be shown for non-baby');
self::assertContains(1, $choiceIds, 'Service with age range 0-14 should be shown for 3-year-old');
self::assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for 3-year-old (age < 6)');
self::assertContains(3, $choiceIds, 'Service without age restrictions should be shown for non-baby');
}
public function testAdultSeesAllApplicableServices(): void
@@ -123,9 +125,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// Adult should see service without age restrictions but not children services
$this->assertNotContains(1, $choiceIds, 'Service with age range 0-14 should be hidden for adult (age > 14)');
$this->assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for adult (age > 14)');
$this->assertContains(3, $choiceIds, 'Service without age restrictions should be shown for adult');
self::assertNotContains(1, $choiceIds, 'Service with age range 0-14 should be hidden for adult (age > 14)');
self::assertNotContains(2, $choiceIds, 'Service with age range 6-14 should be hidden for adult (age > 14)');
self::assertContains(3, $choiceIds, 'Service without age restrictions should be shown for adult');
}
public function testBabyGetRegularPkwInTransportation(): void
@@ -145,9 +147,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// Baby should see BUS and regular PKW, but NOT discounted PKW
$this->assertContains(1, $choiceIds, 'BUS should be shown for baby');
$this->assertContains(3, $choiceIds, 'Regular PKW should be shown for baby');
$this->assertNotContains(2, $choiceIds, 'Discounted PKW should be hidden for baby');
self::assertContains(1, $choiceIds, 'BUS should be shown for baby');
self::assertContains(3, $choiceIds, 'Regular PKW should be shown for baby');
self::assertNotContains(2, $choiceIds, 'Discounted PKW should be hidden for baby');
}
public function testTwoYearOldGetRegularPkwInTransportation(): void
@@ -167,9 +169,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// 2-year-old (at BABY_MAX_AGE) should see BUS and regular PKW, but NOT discounted PKW
$this->assertContains(1, $choiceIds, 'BUS should be shown for 2-year-old');
$this->assertContains(3, $choiceIds, 'Regular PKW should be shown for 2-year-old');
$this->assertNotContains(2, $choiceIds, 'Discounted PKW should be hidden for 2-year-old');
self::assertContains(1, $choiceIds, 'BUS should be shown for 2-year-old');
self::assertContains(3, $choiceIds, 'Regular PKW should be shown for 2-year-old');
self::assertNotContains(2, $choiceIds, 'Discounted PKW should be hidden for 2-year-old');
}
public function testThreeYearOldGetSmartPkwFiltering(): void
@@ -194,9 +196,9 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$choiceIds = array_map(fn (Service $service) => $service->id, $choices);
// 3-year-old is not a baby, should get smart filtering (discounted when available)
$this->assertContains(1, $choiceIds, 'BUS should be shown for 3-year-old');
$this->assertContains(2, $choiceIds, 'Discounted PKW should be shown for 3-year-old when available');
$this->assertNotContains(3, $choiceIds, 'Regular PKW should be hidden when discounted is available');
self::assertContains(1, $choiceIds, 'BUS should be shown for 3-year-old');
self::assertContains(2, $choiceIds, 'Discounted PKW should be shown for 3-year-old when available');
self::assertNotContains(3, $choiceIds, 'Regular PKW should be hidden when discounted is available');
}
public function testBabyFilteringAppliesToMultipleServiceTypes(): void
@@ -214,15 +216,15 @@ class ParticipantFieldOptionsProviderBabyTest extends TestCase
$boardOptions = $this->provider->getFieldOptions('board', $bookingDto, 0);
$boardChoiceIds = array_map(fn (Service $service) => $service->id, $boardOptions['choices']);
$this->assertContains(10, $boardChoiceIds, 'Board with age range 0-5 should be shown for baby');
$this->assertNotContains(11, $boardChoiceIds, 'Board without age range should be hidden for baby');
self::assertContains(10, $boardChoiceIds, 'Board with age range 0-5 should be shown for baby');
self::assertNotContains(11, $boardChoiceIds, 'Board without age range should be hidden for baby');
// Test courses services
$coursesOptions = $this->provider->getFieldOptions('courses', $bookingDto, 0);
$coursesChoiceIds = array_map(fn (Service $service) => $service->id, $coursesOptions['choices']);
$this->assertContains(20, $coursesChoiceIds, 'Course with age range 0-3 should be shown for baby');
$this->assertNotContains(21, $coursesChoiceIds, 'Course without age range should be hidden for baby');
self::assertContains(20, $coursesChoiceIds, 'Course with age range 0-3 should be shown for baby');
self::assertNotContains(21, $coursesChoiceIds, 'Course without age range should be hidden for baby');
}
private function createTravelWithMixedServices(): Travel
@@ -59,9 +59,9 @@ class ParticipantFieldOptionsProviderMandatoryServiceTest extends TestCase
$choiceAttr = $options['choice_attr'];
$attributes = $choiceAttr($mandatoryService);
$this->assertTrue($attributes['readonly']);
$this->assertSame('Diese Leistung ist nicht abwählbar', $attributes['data-tooltip']);
$this->assertArrayNotHasKey('checked', $attributes);
self::assertTrue($attributes['readonly']);
self::assertSame('Diese Leistung ist nicht abwählbar', $attributes['data-tooltip']);
self::assertArrayNotHasKey('checked', $attributes);
}
public function testMandatoryServiceNotSelectedHasNoReadonlyOrChecked(): void
@@ -80,9 +80,9 @@ class ParticipantFieldOptionsProviderMandatoryServiceTest extends TestCase
$choiceAttr = $options['choice_attr'];
$attributes = $choiceAttr($mandatoryService);
$this->assertArrayNotHasKey('readonly', $attributes);
$this->assertArrayNotHasKey('checked', $attributes);
$this->assertArrayNotHasKey('data-tooltip', $attributes);
self::assertArrayNotHasKey('readonly', $attributes);
self::assertArrayNotHasKey('checked', $attributes);
self::assertArrayNotHasKey('data-tooltip', $attributes);
}
public function testNonMandatoryServiceUnaffected(): void
@@ -109,8 +109,8 @@ class ParticipantFieldOptionsProviderMandatoryServiceTest extends TestCase
$choiceAttr = $options['choice_attr'];
$attributes = $choiceAttr($nonMandatoryService);
$this->assertArrayNotHasKey('readonly', $attributes);
$this->assertArrayNotHasKey('checked', $attributes);
self::assertArrayNotHasKey('readonly', $attributes);
self::assertArrayNotHasKey('checked', $attributes);
}
public function testParkingLabelIncludesPrice(): void
@@ -144,7 +144,7 @@ class ParticipantFieldOptionsProviderMandatoryServiceTest extends TestCase
// Do not set participant — age filtering cannot determine choices, returns empty
$options = $this->provider->getFieldOptions('additionalServices', $bookingDto, 0);
$this->assertEmpty($options);
self::assertEmpty($options);
}
private function createMandatoryService(int $id, string $label): Service
@@ -160,6 +160,9 @@ class ParticipantFieldOptionsProviderMandatoryServiceTest extends TestCase
return $service;
}
/**
* @param list<Service> $services
*/
private function createTravelWithAdditionalServices(array $services): Travel
{
$travel = new Travel();
@@ -21,18 +21,18 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
public function testGetFieldName(): void
{
$this->assertSame('licensePlate', $this->handler->getFieldName());
self::assertSame('licensePlate', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$this->assertSame(['parking'], $this->handler->getDependencies());
self::assertSame(['parking'], $this->handler->getDependencies());
}
public function testShouldProcessAlwaysReturnsTrue(): void
{
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
self::assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
}
public function testProcessFieldWithoutParticipant(): void
@@ -61,7 +61,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
}
public function testProcessFieldSetsLicensePlateWhenParkingSelected(): void
@@ -77,7 +77,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertSame('AB-CD 123', $participant->licensePlate);
self::assertSame('AB-CD 123', $participant->licensePlate);
}
public function testProcessFieldHandlesEmptyLicensePlate(): void
@@ -93,7 +93,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
}
public function testProcessFieldHandlesNullLicensePlate(): void
@@ -109,7 +109,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
}
public function testProcessFieldTrimsWhitespace(): void
@@ -125,7 +125,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertSame('AB-CD 123', $participant->licensePlate);
self::assertSame('AB-CD 123', $participant->licensePlate);
}
public function testProcessFieldHandlesWhitespaceOnlyAsEmpty(): void
@@ -141,7 +141,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
}
public function testProcessFieldHandlesNonStringValues(): void
@@ -156,12 +156,12 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
// Test with integer value
$submittedData = ['licensePlate' => 123];
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
// Test with array value
$submittedData = ['licensePlate' => ['invalid']];
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
}
public function testProcessFieldHandlesMissingLicensePlateField(): void
@@ -177,7 +177,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertNull($participant->licensePlate);
self::assertNull($participant->licensePlate);
}
public function testProcessFieldWithDifferentParticipantIndex(): void
@@ -197,7 +197,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
// Process for participant at index 1
$this->handler->processField($submittedData, $bookingDto, 1);
$this->assertNull($participant1->licensePlate); // Should not be affected
$this->assertSame('AB-CD 123', $participant2->licensePlate); // Should be set
self::assertNull($participant1->licensePlate); // Should not be affected
self::assertSame('AB-CD 123', $participant2->licensePlate); // Should be set
}
}
@@ -23,18 +23,18 @@ class ParticipantParkingFieldHandlerTest extends TestCase
public function testGetFieldName(): void
{
$this->assertSame('parking', $this->handler->getFieldName());
self::assertSame('parking', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$this->assertSame(['transportationOutbound', 'transportationInbound', 'dateOfBirth'], $this->handler->getDependencies());
self::assertSame(['transportationOutbound', 'transportationInbound', 'dateOfBirth'], $this->handler->getDependencies());
}
public function testShouldProcessAlwaysReturnsTrue(): void
{
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
self::assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
}
/**
@@ -42,7 +42,7 @@ class ParticipantParkingFieldHandlerTest extends TestCase
*/
public function testNormalizeCheckboxValueReturnsTrueWhenChecked(mixed $value): void
{
$this->assertTrue($this->invokeNormalizeCheckboxValue($value));
self::assertTrue($this->invokeNormalizeCheckboxValue($value));
}
/**
@@ -50,7 +50,7 @@ class ParticipantParkingFieldHandlerTest extends TestCase
*/
public function testNormalizeCheckboxValueReturnsFalseWhenUnchecked(mixed $value): void
{
$this->assertFalse($this->invokeNormalizeCheckboxValue($value));
self::assertFalse($this->invokeNormalizeCheckboxValue($value));
}
public function testProcessFieldWithoutParticipant(): void
@@ -81,8 +81,8 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
$this->assertNull($participant->parkingService);
self::assertFalse($participant->parking);
self::assertNull($participant->parkingService);
}
public function testProcessFieldClearsParkingWhenParticipantIsUnder18(): void
@@ -103,8 +103,8 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
$this->assertNull($participant->parkingService);
self::assertFalse($participant->parking);
self::assertNull($participant->parkingService);
}
public function testProcessFieldClearsParkingWhenParticipantIsExactly17(): void
@@ -130,7 +130,7 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
self::assertFalse($participant->parking);
}
public function testProcessFieldAllowsParkingForAdultWithPkw(): void
@@ -150,7 +150,7 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertTrue($participant->parking);
self::assertTrue($participant->parking);
}
public function testProcessFieldAllowsParkingForExactly18YearOld(): void
@@ -170,7 +170,7 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertTrue($participant->parking);
self::assertTrue($participant->parking);
}
public function testProcessFieldClearsParkingWhenNoDateOfBirth(): void
@@ -190,8 +190,8 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
$this->assertNull($participant->parkingService);
self::assertFalse($participant->parking);
self::assertNull($participant->parkingService);
}
public function testProcessFieldClearsParkingWhenBabyParticipant(): void
@@ -212,8 +212,8 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
$this->assertNull($participant->parkingService);
self::assertFalse($participant->parking);
self::assertNull($participant->parkingService);
}
public function testProcessFieldClearsParkingForChildParticipant(): void
@@ -234,7 +234,7 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
self::assertFalse($participant->parking);
}
public function testProcessFieldSetsParkingToFalseWhenNotSelected(): void
@@ -253,8 +253,8 @@ class ParticipantParkingFieldHandlerTest extends TestCase
$this->handler->processField($submittedData, $bookingDto, 0);
$this->assertFalse($participant->parking);
$this->assertNull($participant->parkingService);
self::assertFalse($participant->parking);
self::assertNull($participant->parkingService);
}
/**
@@ -11,11 +11,14 @@ use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Form\Service\ParticipantTransportationDiscountReplacementFieldHandler;
use App\Service\ServiceAvailabilityCalculator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestCase
{
private ParticipantTransportationDiscountReplacementFieldHandler $handler;
/** @var ServiceAvailabilityCalculator&MockObject */
private ServiceAvailabilityCalculator $serviceAvailabilityCalculator;
protected function setUp(): void
@@ -28,18 +31,18 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
public function testGetFieldName(): void
{
$this->assertSame('transportationDiscountReplacement', $this->handler->getFieldName());
self::assertSame('transportationDiscountReplacement', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$this->assertSame(['transportationOutbound', 'transportationInbound'], $this->handler->getDependencies());
self::assertSame(['transportationOutbound', 'transportationInbound'], $this->handler->getDependencies());
}
public function testShouldProcessAlwaysReturnsTrue(): void
{
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
self::assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess(['some' => 'data'], BookingDto::MODE_EDIT, 5));
}
public function testProcessFieldReplacesDiscountedWithRegularWhenInboundIsBus(): void
@@ -65,16 +68,16 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound was replaced with regular PKW
$this->assertSame($regularPkw->id, $participant->transportationOutbound->id);
$this->assertSame($regularPkw->label, $participant->transportationOutbound->label);
self::assertSame($regularPkw->id, $participant->transportationOutbound->id);
self::assertSame($regularPkw->label, $participant->transportationOutbound->label);
// Assert notification was generated
$this->assertCount(1, $participant->notifications);
self::assertCount(1, $participant->notifications);
$notification = reset($participant->notifications); // Get first notification (keyed by MD5 hash)
$this->assertSame('warning', $notification['type']);
$this->assertStringContainsString('Hinfahrt automatisch angepasst', $notification['message']);
$this->assertStringContainsString('Selbstorganisiert (-15€ Rabatt)', $notification['message']);
$this->assertStringContainsString('Selbstorganisiert', $notification['message']);
self::assertSame('warning', $notification['type']);
self::assertStringContainsString('Hinfahrt automatisch angepasst', $notification['message']);
self::assertStringContainsString('Selbstorganisiert (-15€ Rabatt)', $notification['message']);
self::assertStringContainsString('Selbstorganisiert', $notification['message']);
}
public function testProcessFieldRestoresDiscountedPkwWhenInboundChangesToPkw(): void
@@ -96,7 +99,7 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
// Mock availability: discounted PKW is available
$this->serviceAvailabilityCalculator
->expects($this->once())
->expects(self::once())
->method('isServiceUnavailable')
->with($discountedPkw->id, $bookingDto, 0)
->willReturn(false);
@@ -107,15 +110,15 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound was replaced with discounted PKW
$this->assertSame($discountedPkw->id, $participant->transportationOutbound->id);
$this->assertSame($discountedPkw->label, $participant->transportationOutbound->label);
self::assertSame($discountedPkw->id, $participant->transportationOutbound->id);
self::assertSame($discountedPkw->label, $participant->transportationOutbound->label);
// Assert notification was generated
$this->assertCount(1, $participant->notifications);
self::assertCount(1, $participant->notifications);
$notification = reset($participant->notifications); // Get first notification (keyed by MD5 hash)
$this->assertSame('success', $notification['type']);
$this->assertStringContainsString('Hinfahrt automatisch angepasst', $notification['message']);
$this->assertStringContainsString('wieder verfügbar', $notification['message']);
self::assertSame('success', $notification['type']);
self::assertStringContainsString('Hinfahrt automatisch angepasst', $notification['message']);
self::assertStringContainsString('wieder verfügbar', $notification['message']);
}
public function testProcessFieldDoesNotRestoreDiscountWhenUnavailable(): void
@@ -137,7 +140,7 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
// Mock availability: discounted PKW is sold out
$this->serviceAvailabilityCalculator
->expects($this->once())
->expects(self::once())
->method('isServiceUnavailable')
->with($discountedPkw->id, $bookingDto, 0)
->willReturn(true);
@@ -148,10 +151,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound remains regular PKW
$this->assertSame($regularPkw, $participant->transportationOutbound);
self::assertSame($regularPkw, $participant->transportationOutbound);
// Assert no notification was generated
$this->assertEmpty($participant->notifications);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldNoReplacementWhenOutboundIsBus(): void
@@ -177,10 +180,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound remains BUS (no replacement)
$this->assertSame($busOutbound, $participant->transportationOutbound);
self::assertSame($busOutbound, $participant->transportationOutbound);
// Assert no notification was generated
$this->assertEmpty($participant->notifications);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldNoReplacementWhenOutboundIsRegularPkwAndInboundIsBus(): void
@@ -206,10 +209,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound remains regular PKW (already correct)
$this->assertSame($regularPkw, $participant->transportationOutbound);
self::assertSame($regularPkw, $participant->transportationOutbound);
// Assert no notification was generated
$this->assertEmpty($participant->notifications);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldNoReplacementWhenOutboundIsDiscountedAndInboundIsPkw(): void
@@ -235,10 +238,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound remains discounted PKW (already optimal)
$this->assertSame($discountedPkw, $participant->transportationOutbound);
self::assertSame($discountedPkw, $participant->transportationOutbound);
// Assert no notification was generated
$this->assertEmpty($participant->notifications);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldHandlesNullOutbound(): void
@@ -259,8 +262,8 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert no error and no notification
$this->assertNull($participant->transportationOutbound);
$this->assertEmpty($participant->notifications);
self::assertNull($participant->transportationOutbound);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldHandlesNullInbound(): void
@@ -281,7 +284,7 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
// Mock availability: discounted PKW is available
$this->serviceAvailabilityCalculator
->expects($this->once())
->expects(self::once())
->method('isServiceUnavailable')
->with($discountedPkw->id, $bookingDto, 0)
->willReturn(false);
@@ -292,8 +295,8 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound was replaced with discounted PKW
$this->assertSame($discountedPkw->id, $participant->transportationOutbound->id);
$this->assertSame($discountedPkw->label, $participant->transportationOutbound->label);
self::assertSame($discountedPkw->id, $participant->transportationOutbound->id);
self::assertSame($discountedPkw->label, $participant->transportationOutbound->label);
}
public function testProcessFieldHandlesNullParticipant(): void
@@ -333,7 +336,7 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
// Availability calculator should NOT be called for babies
$this->serviceAvailabilityCalculator
->expects($this->never())
->expects(self::never())
->method('isServiceUnavailable');
$submittedData = [];
@@ -342,10 +345,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound remains regular PKW (no discount restoration for babies)
$this->assertSame($regularPkw->id, $participant->transportationOutbound->id);
self::assertSame($regularPkw->id, $participant->transportationOutbound->id);
// Assert no notification was generated
$this->assertEmpty($participant->notifications);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldSkipsDiscountRestorationForTwoYearOldParticipant(): void
@@ -369,7 +372,7 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
// Availability calculator should NOT be called for babies
$this->serviceAvailabilityCalculator
->expects($this->never())
->expects(self::never())
->method('isServiceUnavailable');
$submittedData = [];
@@ -378,10 +381,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound remains regular PKW
$this->assertSame($regularPkw->id, $participant->transportationOutbound->id);
self::assertSame($regularPkw->id, $participant->transportationOutbound->id);
// Assert no notification was generated
$this->assertEmpty($participant->notifications);
self::assertEmpty($participant->notifications);
}
public function testProcessFieldRestoresDiscountForThreeYearOldParticipant(): void
@@ -406,7 +409,7 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
// Mock availability: discounted PKW is available
$this->serviceAvailabilityCalculator
->expects($this->once())
->expects(self::once())
->method('isServiceUnavailable')
->with($discountedPkw->id, $bookingDto, 0)
->willReturn(false);
@@ -417,10 +420,10 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
$this->handler->processField($submittedData, $bookingDto, 0);
// Assert outbound was replaced with discounted PKW (3-year-old is eligible)
$this->assertSame($discountedPkw->id, $participant->transportationOutbound->id);
self::assertSame($discountedPkw->id, $participant->transportationOutbound->id);
// Assert notification was generated
$this->assertCount(1, $participant->notifications);
self::assertCount(1, $participant->notifications);
}
private function createPkwService(int $id, string $label, float $price, string $direction = DirectionMapper::OUTBOUND_TRAVEL): Service
@@ -447,6 +450,9 @@ class ParticipantTransportationDiscountReplacementFieldHandlerTest extends TestC
return $service;
}
/**
* @param array<int, Service> $services
*/
private function createTravelWithServices(array $services): Travel
{
$travel = new Travel();
@@ -10,6 +10,7 @@ use App\BusProNet\Model\Travel;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Form\Service\ParticipantVegFieldHandler;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class ParticipantVegFieldHandlerTest extends TestCase
@@ -23,22 +24,22 @@ class ParticipantVegFieldHandlerTest extends TestCase
public function testGetFieldName(): void
{
$this->assertEquals('veg', $this->handler->getFieldName());
self::assertEquals('veg', $this->handler->getFieldName());
}
public function testGetDependencies(): void
{
$dependencies = $this->handler->getDependencies();
$this->assertEquals(['dateOfBirth'], $dependencies);
self::assertEquals(['dateOfBirth'], $dependencies);
}
public function testShouldProcessAlwaysReturnsTrue(): void
{
// Should always process to handle deselection cases
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess([], BookingDto::MODE_EDIT, 0));
$this->assertTrue($this->handler->shouldProcess(['veg' => '123'], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess([], BookingDto::MODE_CREATE, 0));
self::assertTrue($this->handler->shouldProcess([], BookingDto::MODE_EDIT, 0));
self::assertTrue($this->handler->shouldProcess(['veg' => '123'], BookingDto::MODE_CREATE, 0));
}
public function testProcessFieldDoesNothingWhenNoParticipant(): void
@@ -63,7 +64,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => null], $bookingDto, 0);
$this->assertNull($participant->veg);
self::assertNull($participant->veg);
}
public function testProcessFieldClearsVegWhenEmptyStringSelection(): void
@@ -77,7 +78,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => ''], $bookingDto, 0);
$this->assertNull($participant->veg);
self::assertNull($participant->veg);
}
public function testProcessFieldClearsVegWhenMissingFromData(): void
@@ -91,7 +92,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField([], $bookingDto, 0);
$this->assertNull($participant->veg);
self::assertNull($participant->veg);
}
public function testProcessFieldClearsVegWhenNotFoundInAvailableServices(): void
@@ -105,7 +106,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => '123'], $bookingDto, 0);
$this->assertNull($participant->veg);
self::assertNull($participant->veg);
}
public function testProcessFieldSetsVegWhenAvailable(): void
@@ -119,7 +120,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => '123'], $bookingDto, 0);
$this->assertSame($vegService, $participant->veg);
self::assertSame($vegService, $participant->veg);
}
public function testProcessFieldWorksWithStringAndIntegerIds(): void
@@ -133,7 +134,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => '123'], $bookingDto, 0); // String selection
$this->assertSame($vegService, $participant->veg);
self::assertSame($vegService, $participant->veg);
}
public function testProcessFieldHandlesEmptyServicesArray(): void
@@ -146,7 +147,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => '123'], $bookingDto, 0);
$this->assertNull($participant->veg);
self::assertNull($participant->veg);
}
public function testProcessFieldSelectsFromMultipleVegOptions(): void
@@ -161,7 +162,7 @@ class ParticipantVegFieldHandlerTest extends TestCase
$this->handler->processField(['veg' => '2'], $bookingDto, 0);
$this->assertSame($vegan, $participant->veg);
self::assertSame($vegan, $participant->veg);
}
public function testGetFieldStateModificationsReturnsEmptyArray(): void
@@ -170,16 +171,16 @@ class ParticipantVegFieldHandlerTest extends TestCase
$result = $this->handler->getFieldStateModifications([], $bookingDto, 0);
$this->assertIsArray($result);
$this->assertEmpty($result);
self::assertIsArray($result);
self::assertEmpty($result);
}
public function testGetAffectedFieldNamesReturnsEmptyArray(): void
{
$result = $this->handler->getAffectedFieldNames();
$this->assertIsArray($result);
$this->assertEmpty($result);
self::assertIsArray($result);
self::assertEmpty($result);
}
private function createService(int $id, string $label = 'Test Service'): Service
@@ -192,6 +193,11 @@ class ParticipantVegFieldHandlerTest extends TestCase
return $service;
}
/**
* @param array<int, Service> $vegServices
*
* @return Travel&MockObject
*/
private function createMockTravel(array $vegServices): Travel
{
$travel = $this->createMock(Travel::class);
@@ -202,6 +208,9 @@ class ParticipantVegFieldHandlerTest extends TestCase
return $travel;
}
/**
* @return BookingDto&MockObject
*/
private function createMockBookingDto(?Travel $travel = null): BookingDto
{
$bookingDto = $this->createMock(BookingDto::class);