'on', ]); $client->disableReboot(); $manager = $this->createMock(PasswordResetManager::class); $manager ->expects(self::once()) ->method('requestPasswordReset') ->with('customer@example.com') ->willReturn(true); self::getContainer()->set(PasswordResetManager::class, $manager); $crawler = $client->request('GET', '/reset-password'); $form = $crawler->selectButton('Passwort-Reset-Link anfordern')->form([ 'form[email]' => 'customer@example.com', ]); $client->submit($form); self::assertResponseRedirects('/'); $client->followRedirect(); self::assertStringContainsString('Du erhältst in Kürze eine E-Mail mit einem Link zum Zurücksetzen deines Passworts', $client->getResponse()->getContent()); } public function testPasswordResetRequestUsesSameGenericSuccessMessageForMissingAccount(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $manager = $this->createMock(PasswordResetManager::class); $manager ->expects(self::once()) ->method('requestPasswordReset') ->with('missing@example.com') ->willReturn(false); self::getContainer()->set(PasswordResetManager::class, $manager); $crawler = $client->request('GET', '/reset-password'); $form = $crawler->selectButton('Passwort-Reset-Link anfordern')->form([ 'form[email]' => 'missing@example.com', ]); $client->submit($form); self::assertResponseRedirects('/'); $client->followRedirect(); self::assertStringContainsString('Du erhältst in Kürze eine E-Mail mit einem Link zum Zurücksetzen deines Passworts', $client->getResponse()->getContent()); } public function testPasswordResetRequestReturns429WhenThrottled(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $email = sprintf('throttle-%s@example.com', bin2hex(random_bytes(4))); $manager = $this->createMock(PasswordResetManager::class); $manager ->expects(self::exactly(5)) ->method('requestPasswordReset') ->with($email) ->willReturn(true); self::getContainer()->set(PasswordResetManager::class, $manager); for ($i = 0; $i < 5; ++$i) { $crawler = $client->request('GET', '/reset-password'); $form = $crawler->selectButton('Passwort-Reset-Link anfordern')->form([ 'form[email]' => $email, ]); $client->submit($form); self::assertResponseRedirects('/'); $client->followRedirect(); } $crawler = $client->request('GET', '/reset-password'); $form = $crawler->selectButton('Passwort-Reset-Link anfordern')->form([ 'form[email]' => $email, ]); $client->submit($form); self::assertResponseStatusCodeSame(429); self::assertStringContainsString(PublicFormRateLimiter::THROTTLED_MESSAGE, $client->getResponse()->getContent()); } public function testPasswordResetConfirmationDisplaysFormAndUpdatesPassword(): void { $client = self::createClient([], [ 'HTTPS' => 'on', ]); $client->disableReboot(); $user = new User('customer@example.com'); $manager = $this->createMock(PasswordResetManager::class); $manager ->expects(self::exactly(2)) ->method('validateResetRequest') ->with(self::isInstanceOf(Request::class)) ->willReturn($user); $manager ->expects(self::once()) ->method('resetPassword') ->with($user, 'new-password'); self::getContainer()->set(PasswordResetManager::class, $manager); $crawler = $client->request('GET', '/reset-password/confirm?email=customer@example.com&nonce=token&expires=9999999999&_hash=signature'); self::assertResponseIsSuccessful(); self::assertSelectorTextContains('h1', 'Neues Passwort'); $form = $crawler->selectButton('Passwort speichern')->form([ 'form[password][first]' => 'new-password', 'form[password][second]' => 'new-password', ]); $client->submit($form); self::assertResponseRedirects('/'); $client->followRedirect(); self::assertStringContainsString('Dein Passwort wurde aktualisiert', $client->getResponse()->getContent()); } }