request('GET', '/mot-de-passe-oublie'); self::assertResponseIsSuccessful(); } public function testEmailStepWithEmptyEmail(): void { $client = static::createClient(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'email', 'email' => '', ]); self::assertResponseIsSuccessful(); } public function testEmailStepSendsCode(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $user = new User(); $user->setEmail('test-forgot-'.uniqid().'@example.com'); $user->setFirstName('Test'); $user->setLastName('User'); $user->setPassword('$2y$13$hashed'); $em->persist($user); $em->flush(); $mailer = $this->createMock(MailerService::class); $mailer->expects(self::once())->method('sendEmail'); static::getContainer()->set(MailerService::class, $mailer); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'email', 'email' => $user->getEmail(), ]); self::assertResponseIsSuccessful(); $em->refresh($user); self::assertNotNull($user->getResetCode()); self::assertNotNull($user->getResetCodeExpiresAt()); } public function testEmailStepIgnoresSsoUser(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $user = new User(); $user->setEmail('test-sso-'.uniqid().'@example.com'); $user->setFirstName('SSO'); $user->setLastName('User'); $user->setPassword(''); $user->setKeycloakId('kc-'.uniqid()); $em->persist($user); $em->flush(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'email', 'email' => $user->getEmail(), ]); self::assertResponseIsSuccessful(); $em->refresh($user); self::assertNull($user->getResetCode()); } public function testEmailStepWithUnknownEmailDoesNotReveal(): void { $client = static::createClient(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'email', 'email' => 'unknown-'.uniqid().'@example.com', ]); self::assertResponseIsSuccessful(); } public function testCodeStepWithEmptyFields(): void { $client = static::createClient(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'code', 'email' => 'test@example.com', 'code' => '', 'password' => '', ]); self::assertResponseIsSuccessful(); } public function testCodeStepWithInvalidCode(): void { $client = static::createClient(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'code', 'email' => 'test@example.com', 'code' => '000000', 'password' => 'NewPassword123!', ]); self::assertResponseIsSuccessful(); } public function testCodeStepWithExpiredCode(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $user = new User(); $user->setEmail('test-expired-'.uniqid().'@example.com'); $user->setFirstName('Test'); $user->setLastName('User'); $user->setPassword('$2y$13$hashed'); $user->setResetCode('123456'); $user->setResetCodeExpiresAt(new \DateTimeImmutable('-1 hour')); $em->persist($user); $em->flush(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'code', 'email' => $user->getEmail(), 'code' => '123456', 'password' => 'NewPassword123!', ]); self::assertResponseIsSuccessful(); } public function testCodeStepWithValidCodeResetsPassword(): void { $client = static::createClient(); $em = static::getContainer()->get(EntityManagerInterface::class); $user = new User(); $user->setEmail('test-reset-'.uniqid().'@example.com'); $user->setFirstName('Test'); $user->setLastName('User'); $user->setPassword('$2y$13$hashed'); $user->setResetCode('654321'); $user->setResetCodeExpiresAt(new \DateTimeImmutable('+15 minutes')); $em->persist($user); $em->flush(); $client->request('POST', '/mot-de-passe-oublie', [ 'step' => 'code', 'email' => $user->getEmail(), 'code' => '654321', 'password' => 'NewPassword123!', ]); self::assertResponseRedirects('/connexion'); $em->refresh($user); self::assertNull($user->getResetCode()); self::assertNull($user->getResetCodeExpiresAt()); self::assertNotSame('$2y$13$hashed', $user->getPassword()); } }