Skip to content

Commit 36d8967

Browse files
committed
Add tests to verify password resets
1 parent 0adfac6 commit 36d8967

1 file changed

Lines changed: 171 additions & 0 deletions

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodedMonkey\Dirigent\Tests\FunctionalTests\Controller\Dashboard;
6+
7+
use CodedMonkey\Dirigent\Controller\Dashboard\DashboardResetPasswordController;
8+
use CodedMonkey\Dirigent\Doctrine\Entity\ResetPasswordRequest;
9+
use CodedMonkey\Dirigent\Doctrine\Entity\User;
10+
use CodedMonkey\Dirigent\Tests\Helper\EntityManagerTestTrait;
11+
use CodedMonkey\Dirigent\Tests\Helper\MockEntityFactoryTrait;
12+
use CodedMonkey\Dirigent\Tests\Helper\WebTestCaseTrait;
13+
use PHPUnit\Framework\Attributes\CoversClass;
14+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\Mime\Email;
17+
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
18+
19+
#[CoversClass(DashboardResetPasswordController::class)]
20+
class DashboardResetPasswordControllerTest extends WebTestCase
21+
{
22+
use EntityManagerTestTrait;
23+
use MockEntityFactoryTrait;
24+
use WebTestCaseTrait;
25+
26+
public function testResetPassword(): void
27+
{
28+
$client = static::createClient();
29+
30+
$user = $this->createMockUser();
31+
$user->setEmail(sprintf('%s@example.com', $user->getUsername()));
32+
$this->persistEntities($user);
33+
34+
$client->request('GET', '/reset-password');
35+
36+
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
37+
38+
$client->submitForm('Send email', [
39+
'reset_password_request_form[email]' => $user->getEmail(),
40+
]);
41+
42+
$this->assertResponseRedirects('/reset-password/sent', Response::HTTP_FOUND);
43+
$this->assertQueuedEmailCount(1);
44+
45+
/** @var Email $email */
46+
$email = $this->getMailerMessage();
47+
48+
$this->assertEmailAddressContains($email, 'to', $user->getEmail());
49+
$this->assertEmailHtmlBodyContains($email, '/reset-password/reset/');
50+
51+
$this->assertNotNull($this->findEntity(ResetPasswordRequest::class, ['user' => $user->getId()]));
52+
53+
preg_match('#/reset-password/reset/[\w-]+#', $email->getHtmlBody(), $matches);
54+
$resetUrl = $matches[0];
55+
56+
$client->request('GET', $resetUrl);
57+
58+
$this->assertResponseRedirects('/reset-password/reset', Response::HTTP_FOUND);
59+
60+
$client->followRedirect();
61+
62+
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
63+
64+
$client->submitForm('Reset', [
65+
'reset_password_form[plainPassword][first]' => 'BrandNewPassword42',
66+
'reset_password_form[plainPassword][second]' => 'BrandNewPassword42',
67+
]);
68+
69+
$this->assertResponseRedirects('/login', Response::HTTP_FOUND);
70+
71+
$this->clearEntities();
72+
$user = $this->findEntity(User::class, $user->getId());
73+
$passwordHasher = $this->getService(UserPasswordHasherInterface::class, 'security.user_password_hasher');
74+
75+
$this->assertTrue($passwordHasher->isPasswordValid($user, 'BrandNewPassword42'));
76+
$this->assertNull($this->findEntity(ResetPasswordRequest::class, ['user' => $user->getId()]));
77+
}
78+
79+
public function testResetPasswordWithMismatchedPasswords(): void
80+
{
81+
$client = static::createClient();
82+
83+
$user = $this->createMockUser();
84+
$user->setEmail(sprintf('%s@example.com', $user->getUsername()));
85+
$this->persistEntities($user);
86+
87+
$client->request('GET', '/reset-password');
88+
89+
$client->submitForm('Send email', [
90+
'reset_password_request_form[email]' => $user->getEmail(),
91+
]);
92+
93+
/** @var Email $email */
94+
$email = $this->getMailerMessage();
95+
96+
preg_match('#/reset-password/reset/[\w-]+#', $email->getHtmlBody(), $matches);
97+
$resetUrl = $matches[0];
98+
99+
$client->request('GET', $resetUrl);
100+
$client->followRedirect();
101+
102+
$crawler = $client->submitForm('Reset', [
103+
'reset_password_form[plainPassword][first]' => 'BrandNewPassword42',
104+
'reset_password_form[plainPassword][second]' => 'AnotherPassword11',
105+
]);
106+
107+
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
108+
$this->assertStringContainsString('The password fields must match', $crawler->filter('.invalid-feedback')->text());
109+
110+
$this->clearEntities();
111+
$user = $this->findEntity(User::class, $user->getId());
112+
$passwordHasher = $this->getService(UserPasswordHasherInterface::class, 'security.user_password_hasher');
113+
114+
$this->assertTrue($passwordHasher->isPasswordValid($user, 'PlainPassword99'));
115+
$this->assertNotNull($this->findEntity(ResetPasswordRequest::class, ['user' => $user->getId()]));
116+
}
117+
118+
public function testRequestPasswordResetForUnknownEmail(): void
119+
{
120+
$client = static::createClient();
121+
122+
$client->request('GET', '/reset-password');
123+
124+
$client->submitForm('Send email', [
125+
'reset_password_request_form[email]' => 'unknown@example.com',
126+
]);
127+
128+
$this->assertResponseRedirects('/reset-password/sent', Response::HTTP_FOUND);
129+
$this->assertQueuedEmailCount(0);
130+
131+
$client->followRedirect();
132+
133+
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
134+
}
135+
136+
public function testSentPageWithoutResetToken(): void
137+
{
138+
$client = static::createClient();
139+
140+
$client->request('GET', '/reset-password/sent');
141+
142+
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
143+
}
144+
145+
public function testResetPasswordWithInvalidToken(): void
146+
{
147+
$client = static::createClient();
148+
149+
$client->request('GET', '/reset-password/reset/' . str_repeat('a', 40));
150+
151+
$this->assertResponseRedirects('/reset-password/reset', Response::HTTP_FOUND);
152+
153+
$client->followRedirect();
154+
155+
$this->assertResponseRedirects('/reset-password', Response::HTTP_FOUND);
156+
157+
$crawler = $client->followRedirect();
158+
159+
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
160+
$this->assertCount(1, $crawler->filter('.alert-danger'));
161+
}
162+
163+
public function testResetPasswordWithoutToken(): void
164+
{
165+
$client = static::createClient();
166+
167+
$client->request('GET', '/reset-password/reset');
168+
169+
$this->assertResponseStatusCodeSame(Response::HTTP_NOT_FOUND);
170+
}
171+
}

0 commit comments

Comments
 (0)