apiClient = $this->createMock(ApiClient::class); $this->crypt = $this->createMock(Crypt::class); $this->logger = $this->createMock(LoggerInterface::class); $this->service = new ParticipantPrepopulationService( $this->apiClient, $this->crypt, $this->logger ); } public function testPrepopulateApplicantWithCompletePersonalData(): void { $user = $this->createUser('test@example.com', 'encrypted_password'); $applicant = new ParticipantDto(); $applicant->index = 0; $personalData = $this->createCompletePersonalData(); $this->crypt->expects($this->once()) ->method('decrypt') ->with('encrypted_password') ->willReturn('decrypted_password'); $this->apiClient->expects($this->once()) ->method('getPersonalData') ->with('test@example.com', 'decrypted_password') ->willReturn($personalData); $this->logger->expects($this->once()) ->method('info') ->with('Prepopulated applicant data from user profile', ['email' => 'test@example.com']); $result = $this->service->prepopulateApplicantFromUser($user, $applicant); // BPN API IDs for linking to existing records $this->assertSame(12345, $result->addressId); $this->assertSame(67890, $result->personId); $this->assertSame('John', $result->firstName); $this->assertSame('Doe', $result->lastName); $this->assertSame('Dr.', $result->title); $this->assertSame('M', $result->gender); $this->assertSame('DE', $result->nationality); $this->assertSame('test@example.com', $result->email); $this->assertSame('+49123456789', $result->mobile); $this->assertSame('180', $result->height); $this->assertSame('75', $result->weight); $this->assertSame('42', $result->shoeSize); $this->assertSame('No smoking room please', $result->remarksRoom); $this->assertSame('AB-CD-1234', $result->licensePlate); $this->assertNotNull($result->dateOfBirth); $this->assertSame('1990-05-15', $result->dateOfBirth->format('Y-m-d')); $this->assertNotNull($result->address); $this->assertSame('Main Street 123', $result->address->street); $this->assertSame('12345', $result->address->postCode); $this->assertSame('Berlin', $result->address->city); $this->assertSame('DE', $result->address->country); $this->assertSame('Mitte', $result->address->district); } public function testPrepopulateApplicantWithPartialPersonalData(): void { $user = $this->createUser('test@example.com', 'encrypted_password'); $applicant = new ParticipantDto(); $applicant->index = 0; $personalData = $this->createPartialPersonalData(); $this->crypt->expects($this->once()) ->method('decrypt') ->willReturn('decrypted_password'); $this->apiClient->expects($this->once()) ->method('getPersonalData') ->willReturn($personalData); $this->logger->expects($this->once()) ->method('info'); $result = $this->service->prepopulateApplicantFromUser($user, $applicant); // Required fields should be populated $this->assertSame('Jane', $result->firstName); $this->assertSame('Smith', $result->lastName); $this->assertSame('jane@example.com', $result->email); // Optional fields should be null $this->assertNull($result->title); $this->assertNull($result->gender); $this->assertNull($result->nationality); $this->assertNull($result->mobile); $this->assertNull($result->height); $this->assertNull($result->weight); $this->assertNull($result->shoeSize); $this->assertNull($result->remarksRoom); $this->assertNull($result->licensePlate); } public function testPrepopulateApplicantWithApiNotificationError(): void { $user = $this->createUser('test@example.com', 'encrypted_password'); $applicant = new ParticipantDto(); $applicant->index = 0; $notification = new Notification(401, 'Authentication failed'); $this->crypt->expects($this->once()) ->method('decrypt') ->willReturn('decrypted_password'); $this->apiClient->expects($this->once()) ->method('getPersonalData') ->willReturn($notification); $this->logger->expects($this->once()) ->method('warning') ->with('Failed to fetch personal data for prepopulation', [ 'email' => 'test@example.com', 'code' => 401, 'message' => 'Authentication failed', ]); $this->logger->expects($this->never()) ->method('info'); $result = $this->service->prepopulateApplicantFromUser($user, $applicant); // Should return unchanged applicant $this->assertNull($result->firstName); $this->assertNull($result->lastName); $this->assertNull($result->email); } public function testPrepopulateApplicantWithDecryptionException(): void { $user = $this->createUser('test@example.com', 'encrypted_password'); $applicant = new ParticipantDto(); $applicant->index = 0; $this->crypt->expects($this->once()) ->method('decrypt') ->willThrowException(new \RuntimeException('Decryption failed')); $this->apiClient->expects($this->never()) ->method('getPersonalData'); $this->logger->expects($this->once()) ->method('error') ->with('Exception during applicant prepopulation', [ 'error' => 'Decryption failed', 'email' => 'test@example.com', ]); $result = $this->service->prepopulateApplicantFromUser($user, $applicant); // Should return unchanged applicant $this->assertNull($result->firstName); $this->assertNull($result->lastName); $this->assertNull($result->email); } public function testPrepopulateApplicantWithApiException(): void { $user = $this->createUser('test@example.com', 'encrypted_password'); $applicant = new ParticipantDto(); $applicant->index = 0; $this->crypt->expects($this->once()) ->method('decrypt') ->willReturn('decrypted_password'); $this->apiClient->expects($this->once()) ->method('getPersonalData') ->willThrowException(new \RuntimeException('API connection failed')); $this->logger->expects($this->once()) ->method('error') ->with('Exception during applicant prepopulation', [ 'error' => 'API connection failed', 'email' => 'test@example.com', ]); $result = $this->service->prepopulateApplicantFromUser($user, $applicant); // Should return unchanged applicant $this->assertNull($result->firstName); $this->assertNull($result->lastName); $this->assertNull($result->email); } public function testPrepopulatePreservesBookingSpecificFields(): void { $user = $this->createUser('test@example.com', 'encrypted_password'); $applicant = new ParticipantDto(); $applicant->index = 0; $applicant->assignedRoomId = 42; $applicant->bulkInsuranceBooking = true; $personalData = $this->createCompletePersonalData(); $this->crypt->expects($this->once()) ->method('decrypt') ->willReturn('decrypted_password'); $this->apiClient->expects($this->once()) ->method('getPersonalData') ->willReturn($personalData); $result = $this->service->prepopulateApplicantFromUser($user, $applicant); // Personal data should be updated $this->assertSame('John', $result->firstName); $this->assertSame('Doe', $result->lastName); // Booking-specific fields should be preserved $this->assertSame(42, $result->assignedRoomId); $this->assertTrue($result->bulkInsuranceBooking); } private function createUser(string $email, string $encryptedPassword): User { $user = new User($email); $user->setPassword($encryptedPassword); return $user; } private function createCompletePersonalData(): PersonalData { $personalData = new PersonalData(); $personalData->addressId = 12345; $personalData->personId = 67890; $personalData->firstName = 'John'; $personalData->name = 'Doe'; $personalData->title = 'Dr.'; $personalData->gender = 'M'; $personalData->nationality = 'DE'; $personalData->dateOfBirth = new \DateTimeImmutable('1990-05-15'); $personalData->height = '180'; $personalData->weight = '75'; $personalData->shoeSize = '42'; $personalData->remarksRoom = 'No smoking room please'; $personalData->licensePlate = 'AB-CD-1234'; $personalData->communication = new Communication(); $personalData->communication->email = 'test@example.com'; $personalData->communication->mobile = '+49123456789'; $personalData->address = new Address(); $personalData->address->street = 'Main Street 123'; $personalData->address->postCode = '12345'; $personalData->address->city = 'Berlin'; $personalData->address->country = 'DE'; $personalData->address->district = 'Mitte'; return $personalData; } private function createPartialPersonalData(): PersonalData { $personalData = new PersonalData(); $personalData->firstName = 'Jane'; $personalData->name = 'Smith'; $personalData->dateOfBirth = new \DateTimeImmutable('1995-03-20'); $personalData->communication = new Communication(); $personalData->communication->email = 'jane@example.com'; $personalData->address = new Address(); $personalData->address->street = 'Second Street 45'; $personalData->address->postCode = '54321'; $personalData->address->city = 'Munich'; $personalData->address->country = 'DE'; return $personalData; } }