'on', 'HTTP_HX_REQUEST' => 'true', ]); $client->disableReboot(); $userRepository = $this->createMock(UserRepository::class); $userRepository ->expects(self::once()) ->method('findOneByNormalizedEmail') ->with('customer@example.com') ->willReturn(null); $rateLimiter = $this->createMock(PublicFormRateLimiter::class); $rateLimiter ->expects(self::once()) ->method('isRegistrationAllowed') ->with('customer@example.com', self::isInstanceOf(Request::class)) ->willReturn(false); $apiClient = $this->createMock(ApiClient::class); $this->configureBaseData($apiClient); $apiClient->expects(self::never())->method('register'); $apiClient->expects(self::never())->method('getCrmAttributesWithPassword'); $apiClient->expects(self::never())->method('getPersonalDataWithPassword'); self::getContainer()->set(UserRepository::class, $userRepository); self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter); self::getContainer()->set(ApiClient::class, $apiClient); $crawler = $client->request('GET', '/registration'); $form = $crawler->selectButton('Jetzt registrieren')->form([ 'registration[firstName]' => 'Customer', 'registration[name]' => 'Example', 'registration[plainPassword][first]' => 'Str0ng-Passw0rd!', 'registration[plainPassword][second]' => 'Str0ng-Passw0rd!', 'registration[personalData][gender]' => 'M', 'registration[personalData][dateOfBirth][day]' => '1', 'registration[personalData][dateOfBirth][month]' => '1', 'registration[personalData][dateOfBirth][year]' => '1990', 'registration[personalData][street]' => 'Main Street 1', 'registration[personalData][postCode]' => '12345', 'registration[personalData][city]' => 'Berlin', 'registration[personalData][country]' => 'DE', 'registration[personalData][nationality]' => 'DE', 'registration[personalData][email]' => 'Customer@Example.COM', 'registration[personalData][mobile]' => '0123456789', ]); $client->submit($form); self::assertResponseStatusCodeSame(429); self::assertStringContainsString(PublicFormRateLimiter::THROTTLED_MESSAGE, $client->getResponse()->getContent()); } public function testDuplicateLocalUserRedirectsToResetPassword(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $existingUser = new User('customer@example.com'); $userRepository = $this->createMock(UserRepository::class); $userRepository ->expects(self::once()) ->method('findOneByNormalizedEmail') ->with('customer@example.com') ->willReturn($existingUser); $rateLimiter = $this->createMock(PublicFormRateLimiter::class); $rateLimiter->expects(self::never())->method('isRegistrationAllowed'); $apiClient = $this->createMock(ApiClient::class); $this->configureBaseData($apiClient); $apiClient->expects(self::never())->method('register'); $apiClient->expects(self::never())->method('getCrmAttributesWithPassword'); $apiClient->expects(self::never())->method('getPersonalDataWithPassword'); self::getContainer()->set(UserRepository::class, $userRepository); self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter); self::getContainer()->set(ApiClient::class, $apiClient); $crawler = $client->request('GET', '/registration'); $form = $crawler->selectButton('Jetzt registrieren')->form([ 'registration[firstName]' => 'Customer', 'registration[name]' => 'Example', 'registration[plainPassword][first]' => 'Str0ng-Passw0rd!', 'registration[plainPassword][second]' => 'Str0ng-Passw0rd!', 'registration[personalData][gender]' => 'M', 'registration[personalData][dateOfBirth][day]' => '1', 'registration[personalData][dateOfBirth][month]' => '1', 'registration[personalData][dateOfBirth][year]' => '1990', 'registration[personalData][street]' => 'Main Street 1', 'registration[personalData][postCode]' => '12345', 'registration[personalData][city]' => 'Berlin', 'registration[personalData][country]' => 'DE', 'registration[personalData][nationality]' => 'DE', 'registration[personalData][email]' => 'Customer@Example.COM', 'registration[personalData][mobile]' => '0123456789', ]); $client->submit($form); self::assertResponseRedirects('/reset-password'); } public function testIncompleteRegistrationSubmissionIsRejectedByValidation(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $userRepository = $this->createMock(UserRepository::class); $userRepository->expects(self::never())->method('findOneByNormalizedEmail'); $rateLimiter = $this->createMock(PublicFormRateLimiter::class); $rateLimiter->expects(self::never())->method('isRegistrationAllowed'); $apiClient = $this->createMock(ApiClient::class); $this->configureBaseData($apiClient); $apiClient->expects(self::never())->method('register'); $apiClient->expects(self::never())->method('getCrmAttributesWithPassword'); $apiClient->expects(self::never())->method('getPersonalDataWithPassword'); self::getContainer()->set(UserRepository::class, $userRepository); self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter); self::getContainer()->set(ApiClient::class, $apiClient); $crawler = $client->request('GET', '/registration'); $form = $crawler->selectButton('Jetzt registrieren')->form([ 'registration[firstName]' => 'Customer', 'registration[name]' => 'Example', 'registration[plainPassword][first]' => 'Str0ng-Passw0rd!', 'registration[plainPassword][second]' => 'Str0ng-Passw0rd!', 'registration[personalData][gender]' => 'M', 'registration[personalData][dateOfBirth][day]' => '1', 'registration[personalData][dateOfBirth][month]' => '1', 'registration[personalData][dateOfBirth][year]' => '1990', 'registration[personalData][street]' => 'Main Street 1', 'registration[personalData][postCode]' => '12345', 'registration[personalData][city]' => 'Berlin', 'registration[personalData][country]' => 'DE', 'registration[personalData][nationality]' => 'DE', 'registration[personalData][email]' => 'Customer@Example.COM', ]); $client->submit($form); self::assertResponseStatusCodeSame(422); } public function testMismatchedPasswordRegistrationSubmissionIsRejectedBeforeApiCalls(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $userRepository = $this->createMock(UserRepository::class); $userRepository->expects(self::never())->method('findOneByNormalizedEmail'); $rateLimiter = $this->createMock(PublicFormRateLimiter::class); $rateLimiter->expects(self::never())->method('isRegistrationAllowed'); $apiClient = $this->createMock(ApiClient::class); $apiClient->expects(self::never())->method('register'); $apiClient->expects(self::never())->method('getCrmAttributesWithPassword'); $apiClient->expects(self::never())->method('getPersonalDataWithPassword'); self::getContainer()->set(UserRepository::class, $userRepository); self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter); self::getContainer()->set(ApiClient::class, $apiClient); $crawler = $client->request('GET', '/registration'); $form = $crawler->selectButton('Jetzt registrieren')->form([ 'registration[firstName]' => 'Customer', 'registration[name]' => 'Example', 'registration[plainPassword][first]' => 'Str0ng-Passw0rd!', 'registration[plainPassword][second]' => 'Str0ng-Passw0rd!!', 'registration[personalData][gender]' => 'M', 'registration[personalData][dateOfBirth][day]' => '1', 'registration[personalData][dateOfBirth][month]' => '1', 'registration[personalData][dateOfBirth][year]' => '1990', 'registration[personalData][street]' => 'Main Street 1', 'registration[personalData][postCode]' => '12345', 'registration[personalData][city]' => 'Berlin', 'registration[personalData][country]' => 'DE', 'registration[personalData][nationality]' => 'DE', 'registration[personalData][email]' => 'Customer@Example.COM', 'registration[personalData][mobile]' => '0123456789', ]); $client->submit($form); self::assertResponseStatusCodeSame(422); self::assertStringContainsString('Die beiden Passwortangaben müssen identisch sein.', $client->getResponse()->getContent()); } public function testSuccessfulRegistrationDoesNotRefetchPersonalData(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $userRepository = $this->createMock(UserRepository::class); $userRepository ->expects(self::once()) ->method('findOneByNormalizedEmail') ->with('customer@example.com') ->willReturn(null); $rateLimiter = $this->createMock(PublicFormRateLimiter::class); $rateLimiter ->expects(self::once()) ->method('isRegistrationAllowed') ->with('customer@example.com', self::isInstanceOf(Request::class)) ->willReturn(true); $apiClient = $this->createMock(ApiClient::class); $this->configureBaseData($apiClient); $apiClient ->expects(self::once()) ->method('register') ->with(self::callback(function ($registrationData): bool { self::assertSame('customer@example.com', $registrationData->communication->email); return true; })) ->willReturn(new RegistrationResponse(123, 456, true)); $apiClient ->expects(self::never()) ->method('getPersonalDataWithPassword'); $apiClient ->expects(self::never()) ->method('getCrmAttributesWithPassword'); $passwordHasher = $this->createMock(UserPasswordHasherInterface::class); $passwordHasher ->expects(self::once()) ->method('hashPassword') ->with(self::isInstanceOf(User::class), 'Str0ng-Passw0rd!') ->willReturn('hashed-secret'); $persistedUser = null; $entityManager = $this->createMock(EntityManagerInterface::class); $entityManager ->expects(self::once()) ->method('persist') ->with(self::callback(static function (User $user) use (&$persistedUser): bool { $persistedUser = $user; return true; })); $entityManager ->expects(self::once()) ->method('flush'); self::getContainer()->set(UserRepository::class, $userRepository); self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter); self::getContainer()->set(ApiClient::class, $apiClient); self::getContainer()->set(UserPasswordHasherInterface::class, $passwordHasher); self::getContainer()->set(EntityManagerInterface::class, $entityManager); $crawler = $client->request('GET', '/registration'); $form = $crawler->selectButton('Jetzt registrieren')->form([ 'registration[firstName]' => 'Customer', 'registration[name]' => 'Example', 'registration[plainPassword][first]' => 'Str0ng-Passw0rd!', 'registration[plainPassword][second]' => 'Str0ng-Passw0rd!', 'registration[personalData][gender]' => 'M', 'registration[personalData][dateOfBirth][day]' => '1', 'registration[personalData][dateOfBirth][month]' => '1', 'registration[personalData][dateOfBirth][year]' => '1990', 'registration[personalData][street]' => 'Main Street 1', 'registration[personalData][postCode]' => '12345', 'registration[personalData][city]' => 'Berlin', 'registration[personalData][country]' => 'DE', 'registration[personalData][nationality]' => 'DE', 'registration[personalData][email]' => 'Customer@Example.COM', 'registration[personalData][mobile]' => '0123456789', ]); $client->submit($form); self::assertResponseRedirects('/'); self::assertInstanceOf(User::class, $persistedUser); self::assertSame('customer@example.com', $persistedUser->getEmail()); self::assertSame('hashed-secret', $persistedUser->getPassword()); self::assertSame(123, $persistedUser->getAddressId()); self::assertSame(456, $persistedUser->getPersonId()); self::assertSame(['ROLE_USER'], $persistedUser->getRoles()); self::assertSame([], $persistedUser->getHotelCodes()); self::assertTrue($persistedUser->isProfileComplete()); } public function testRegistrationApiFailureRendersFormInsteadOfResetPassword(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $userRepository = $this->createMock(UserRepository::class); $userRepository ->expects(self::once()) ->method('findOneByNormalizedEmail') ->with('customer@example.com') ->willReturn(null); $rateLimiter = $this->createMock(PublicFormRateLimiter::class); $rateLimiter ->expects(self::once()) ->method('isRegistrationAllowed') ->with('customer@example.com', self::isInstanceOf(Request::class)) ->willReturn(true); $apiClient = $this->createMock(ApiClient::class); $this->configureBaseData($apiClient); $apiClient ->expects(self::once()) ->method('register') ->willThrowException(new ApiClientException('Registrierung momentan nicht möglich.')); $apiClient ->expects(self::never()) ->method('getCrmAttributesWithPassword'); $apiClient ->expects(self::never()) ->method('getPersonalDataWithPassword'); $entityManager = $this->createMock(EntityManagerInterface::class); $entityManager ->expects(self::never()) ->method('persist'); $entityManager ->expects(self::never()) ->method('flush'); self::getContainer()->set(UserRepository::class, $userRepository); self::getContainer()->set(PublicFormRateLimiter::class, $rateLimiter); self::getContainer()->set(ApiClient::class, $apiClient); self::getContainer()->set(EntityManagerInterface::class, $entityManager); $crawler = $client->request('GET', '/registration'); $form = $crawler->selectButton('Jetzt registrieren')->form([ 'registration[firstName]' => 'Customer', 'registration[name]' => 'Example', 'registration[plainPassword][first]' => 'Str0ng-Passw0rd!', 'registration[plainPassword][second]' => 'Str0ng-Passw0rd!', 'registration[personalData][gender]' => 'M', 'registration[personalData][dateOfBirth][day]' => '1', 'registration[personalData][dateOfBirth][month]' => '1', 'registration[personalData][dateOfBirth][year]' => '1990', 'registration[personalData][street]' => 'Main Street 1', 'registration[personalData][postCode]' => '12345', 'registration[personalData][city]' => 'Berlin', 'registration[personalData][country]' => 'DE', 'registration[personalData][nationality]' => 'DE', 'registration[personalData][email]' => 'Customer@Example.COM', 'registration[personalData][mobile]' => '0123456789', ]); $client->submit($form); self::assertResponseStatusCodeSame(502); self::assertStringContainsString('Registrierung momentan nicht möglich.', $client->getResponse()->getContent()); } private function configureBaseData(ApiClient $apiClient): void { $country = new Country(); $country->token = 'DE'; $country->name = 'Germany'; $country->nationality = 'DE'; $apiClient ->method('getBaseData') ->willReturn(new BaseData(['DE' => $country])); } }