priceCalculator = $this->createMock(BookingPriceCalculatorService::class); $this->priceCalculator ->method('calculateIndividualParticipantPriceExcludingInsurance') ->willReturn(500.0); // Default test price $this->service = new InsuranceMatchingService($this->priceCalculator); // Set a fixed test date for consistent test results Carbon::setTestNow('2024-06-01 12:00:00'); } protected function tearDown(): void { // Reset Carbon's test now after each test Carbon::setTestNow(); } public function testGetEligibleInsurancesWithMatchingCriteria(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance([ 'ageFrom' => 20, 'ageTo' => 50, 'travelDateFrom' => new \DateTimeImmutable('2024-01-01'), 'travelDateTo' => new \DateTimeImmutable('2024-12-31'), 'bookingDateFrom' => new \DateTimeImmutable('2024-01-01'), 'bookingDateTo' => new \DateTimeImmutable('2024-12-31'), 'travelPriceFrom' => 0.0, 'travelPriceTo' => 1000.0, 'travelDurationFrom' => 1, 'travelDurationTo' => 14, ]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertCount(1, $result); $this->assertContains($insurance, $result); } public function testGetEligibleInsurancesExcludesInsuranceWithAgeTooYoung(): void { $participant = $this->createParticipant('2010-06-15'); // 14 years old in 2024 $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance(['ageFrom' => 18, 'ageTo' => 65]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithAgeTooOld(): void { $participant = $this->createParticipant('1950-06-15'); // 74 years old in 2024 $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance(['ageFrom' => 18, 'ageTo' => 65]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithTravelDateTooEarly(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance([ 'travelDateFrom' => new \DateTimeImmutable('2024-09-01'), 'travelDateTo' => new \DateTimeImmutable('2024-12-31'), ]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithTravelDateTooLate(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance([ 'travelDateFrom' => new \DateTimeImmutable('2024-01-01'), 'travelDateTo' => new \DateTimeImmutable('2024-07-31'), ]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithBookingDateTooEarly(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance([ 'bookingDateFrom' => new \DateTimeImmutable('2025-01-01'), 'bookingDateTo' => new \DateTimeImmutable('2025-12-31'), ]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithBookingDateTooLate(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance([ 'bookingDateFrom' => new \DateTimeImmutable('2023-01-01'), 'bookingDateTo' => new \DateTimeImmutable('2023-12-31'), ]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithTravelDurationTooShort(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-03'); // 2 days $insurance = $this->createInsurance(['travelDurationFrom' => 7, 'travelDurationTo' => 30]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesExcludesInsuranceWithTravelDurationTooLong(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-31'); // 30 days $insurance = $this->createInsurance(['travelDurationFrom' => 1, 'travelDurationTo' => 14]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertEmpty($result); } public function testGetEligibleInsurancesHandlesParticipantWithoutBirthDate(): void { $participant = new ParticipantDto(); $participant->index = 0; // Set participant index for price calculations $participant->dateOfBirth = null; $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance(['ageFrom' => 18, 'ageTo' => 65]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); // Participants without birth date should now have insurances available // (field visibility is controlled by field state conditions, not service logic) $this->assertNotEmpty($result); $this->assertCount(1, $result); $this->assertSame($insurance, $result[0]); } public function testGetEligibleInsurancesWithNullConstraints(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); // Insurance with no constraints should match any criteria $insurance = $this->createInsurance([]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertCount(1, $result); $this->assertContains($insurance, $result); } public function testGetEligibleInsurancesWithMultipleInsurances(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); $eligibleInsurance1 = $this->createInsurance(['ageFrom' => 20, 'ageTo' => 50]); $eligibleInsurance2 = $this->createInsurance(['ageFrom' => 30, 'ageTo' => 40]); $ineligibleInsurance = $this->createInsurance(['ageFrom' => 60, 'ageTo' => 80]); $insurances = [$eligibleInsurance1, $eligibleInsurance2, $ineligibleInsurance]; $result = $this->service->getEligibleInsurances($insurances, $participant, $booking); $this->assertCount(2, $result); $this->assertContains($eligibleInsurance1, $result); $this->assertContains($eligibleInsurance2, $result); $this->assertNotContains($ineligibleInsurance, $result); } public function testGetEligibleInsurancesWithAgeExactlyAtBoundary(): void { $participant = $this->createParticipant('1990-08-01'); // Exactly 34 on travel start $booking = $this->createBooking('2024-08-01', '2024-08-08'); $insurance = $this->createInsurance(['ageFrom' => 34, 'ageTo' => 34]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertCount(1, $result); $this->assertContains($insurance, $result); } public function testGetEligibleInsurancesWithTravelDurationExactlyAtBoundary(): void { $participant = $this->createParticipant('1990-06-15'); $booking = $this->createBooking('2024-08-01', '2024-08-08'); // Exactly 7 days $insurance = $this->createInsurance(['travelDurationFrom' => 7, 'travelDurationTo' => 7]); $result = $this->service->getEligibleInsurances([$insurance], $participant, $booking); $this->assertCount(1, $result); $this->assertContains($insurance, $result); } private function createParticipant(string $dateOfBirth): ParticipantDto { $participant = new ParticipantDto(); $participant->index = 0; // Set participant index for price calculations $participant->dateOfBirth = new \DateTimeImmutable($dateOfBirth); return $participant; } private function createBooking(string $travelDateFrom, string $travelDateTo): BookingDto { $travel = $this->createTravel($travelDateFrom, $travelDateTo); $booking = new BookingDto($travel, 1); return $booking; } private function createTravel(string $dateFrom, string $dateTo): \App\BusProNet\Model\Travel { $travel = new \App\BusProNet\Model\Travel(); $travel->dateFrom = new \DateTimeImmutable($dateFrom); $travel->dateTo = new \DateTimeImmutable($dateTo); return $travel; } private function createInsurance(array $constraints = []): Insurance { $insurance = new Insurance(); foreach ($constraints as $property => $value) { $insurance->$property = $value; } return $insurance; } }