7
7
8
8
namespace Magento \Customer \Controller ;
9
9
10
+ use Magento \Config \Model \ResourceModel \Config as CoreConfig ;
11
+ use Magento \Customer \Model \CustomerRegistry ;
12
+ use Magento \Customer \Model \ResourceModel \Customer as CustomerResource ;
13
+ use Magento \Customer \Model \Session ;
14
+ use Magento \Framework \App \Config \ReinitableConfigInterface ;
15
+ use Magento \Framework \App \Config \ScopeConfigInterface ;
16
+ use Magento \Framework \App \Http ;
10
17
use Magento \Framework \App \Request \Http as HttpRequest ;
18
+ use Magento \Framework \Exception \NoSuchEntityException ;
19
+ use Magento \Framework \Intl \DateTimeFactory ;
20
+ use Magento \Framework \Math \Random ;
11
21
use Magento \Framework \Message \MessageInterface ;
12
22
use Magento \Framework \ObjectManagerInterface ;
23
+ use Magento \Framework \Serialize \Serializer \Json ;
24
+ use Magento \Framework \Stdlib \CookieManagerInterface ;
25
+ use Magento \Framework \Stdlib \DateTime ;
13
26
use Magento \TestFramework \Helper \Bootstrap ;
27
+ use Magento \TestFramework \Helper \Xpath ;
14
28
use Magento \TestFramework \Mail \Template \TransportBuilderMock ;
29
+ use Magento \TestFramework \Request ;
15
30
use Magento \TestFramework \TestCase \AbstractController ;
31
+ use Magento \Framework \Api \SearchCriteriaBuilder ;
32
+ use Magento \Theme \Controller \Result \MessagePlugin ;
16
33
17
34
/**
18
35
* Class checks password forgot scenarios
@@ -28,6 +45,36 @@ class ForgotPasswordPostTest extends AbstractController
28
45
/** @var TransportBuilderMock */
29
46
private $ transportBuilderMock ;
30
47
48
+ /**
49
+ * @var CoreConfig
50
+ */
51
+ protected $ resourceConfig ;
52
+
53
+ /**
54
+ * @var ReinitableConfigInterface
55
+ */
56
+ private $ reinitableConfig ;
57
+
58
+ /**
59
+ * @var ScopeConfigInterface
60
+ */
61
+ private $ scopeConfig ;
62
+
63
+ /**
64
+ * @var DateTimeFactory
65
+ */
66
+ private $ dateTimeFactory ;
67
+
68
+ /**
69
+ * @var CustomerResource
70
+ */
71
+ private $ customerResource ;
72
+
73
+ /**
74
+ * @var Random
75
+ */
76
+ private $ random ;
77
+
31
78
/**
32
79
* @inheritdoc
33
80
*/
@@ -37,6 +84,12 @@ protected function setUp(): void
37
84
38
85
$ this ->objectManager = Bootstrap::getObjectManager ();
39
86
$ this ->transportBuilderMock = $ this ->objectManager ->get (TransportBuilderMock::class);
87
+ $ this ->resourceConfig = $ this ->_objectManager ->get (CoreConfig::class);
88
+ $ this ->reinitableConfig = $ this ->_objectManager ->get (ReinitableConfigInterface::class);
89
+ $ this ->scopeConfig = Bootstrap::getObjectManager ()->get (ScopeConfigInterface::class);
90
+ $ this ->dateTimeFactory = $ this ->objectManager ->get (DateTimeFactory::class);
91
+ $ this ->customerResource = $ this ->objectManager ->get (CustomerResource::class);
92
+ $ this ->random = $ this ->objectManager ->get (Random::class);
40
93
}
41
94
42
95
/**
@@ -134,4 +187,161 @@ private function assertSuccessSessionMessage(string $email): void
134
187
);
135
188
$ this ->assertSessionMessages ($ this ->equalTo ([$ message ]), MessageInterface::TYPE_SUCCESS );
136
189
}
190
+
191
+ /**
192
+ * @magentoConfigFixture current_store customer/captcha/enable 0
193
+ * @magentoConfigFixture current_store customer/password/min_time_between_password_reset_requests 0
194
+ * @magentoConfigFixture current_store customer/password/max_number_password_reset_requests 0
195
+ * @magentoDataFixture Magento/Customer/_files/customer.php
196
+ *
197
+ * @return void
198
+ * @throws NoSuchEntityException
199
+ */
200
+ public function testResetLinkSentAfterForgotPassword (): void
201
+ {
202
+ $ defaultExpirationPeriod = 2 ;
203
+ $ actualExpirationPeriod = (int ) $ this ->scopeConfig ->getValue (
204
+ 'customer/password/reset_link_expiration_period ' ,
205
+ \Magento \Store \Model \ScopeInterface::SCOPE_WEBSITE
206
+ );
207
+ $ this ->assertEquals (
208
+ $ defaultExpirationPeriod ,
209
+ $ actualExpirationPeriod
210
+ );
211
+
212
+ $ this ->resourceConfig ->saveConfig (
213
+ 'customer/password/reset_link_expiration_period ' ,
214
+ 1 ,
215
+ ScopeConfigInterface::SCOPE_TYPE_DEFAULT ,
216
+ 0
217
+ );
218
+
219
+ $ email = 'customer@example.com ' ;
220
+
221
+ $ this ->getRequest ()->setPostValue (['email ' => $ email ]);
222
+ $ this ->getRequest ()->setMethod (HttpRequest::METHOD_POST );
223
+
224
+ $ this ->dispatch ('customer/account/forgotPasswordPost ' );
225
+ $ this ->assertRedirect ($ this ->stringContains ('customer/account/ ' ));
226
+ $ this ->assertSessionMessages (
227
+ $ this ->equalTo (
228
+ [
229
+ "If there is an account associated with {$ email } you will receive an email with a link "
230
+ . "to reset your password. "
231
+ ]
232
+ ),
233
+ MessageInterface::TYPE_SUCCESS
234
+ );
235
+
236
+ $ sendMessage = $ this ->transportBuilderMock ->getSentMessage ()->getBody ()->getParts ()[0 ]->getRawContent ();
237
+
238
+ $ this ->assertStringContainsString (
239
+ 'There was recently a request to change the password for your account ' ,
240
+ $ sendMessage
241
+ );
242
+
243
+ /** @var CustomerRegistry $customerRegistry */
244
+ $ customerRegistry = $ this ->_objectManager ->get (CustomerRegistry::class);
245
+ $ customerData = $ customerRegistry ->retrieveByEmail ($ email );
246
+ $ token = $ customerData ->getRpToken ();
247
+ $ customerId = $ customerData ->getId ();
248
+
249
+ $ this ->assertEquals (
250
+ 1 ,
251
+ Xpath::getElementsCountForXpath (
252
+ sprintf (
253
+ '//a[contains(@href, \'customer/account/createPassword/?id=%1$d&token=%2$s \')] ' ,
254
+ $ customerId ,
255
+ $ token
256
+ ),
257
+ $ sendMessage
258
+ )
259
+ );
260
+ }
261
+
262
+ /**
263
+ * @magentoConfigFixture current_store customer/captcha/enable 0
264
+ * @magentoConfigFixture current_store customer/password/min_time_between_password_reset_requests 0
265
+ * @magentoConfigFixture current_store customer/password/max_number_password_reset_requests 0
266
+ * @magentoDataFixture Magento/Customer/_files/customer.php
267
+ *
268
+ * @depends testResetLinkSentAfterForgotPassword
269
+ * @return void
270
+ * @throws NoSuchEntityException
271
+ * @throws \Magento\Framework\Exception\AlreadyExistsException
272
+ * @throws \Magento\Framework\Exception\AuthenticationException
273
+ * @throws \Magento\Framework\Exception\LocalizedException
274
+ */
275
+ public function testResetLinkExpirationByTimeout (): void
276
+ {
277
+ $ this ->reinitableConfig ->reinit ();
278
+ $ email = 'customer@example.com ' ;
279
+
280
+ /** @var CustomerRegistry $customerRegistry */
281
+ $ customerRegistry = $ this ->_objectManager ->get (CustomerRegistry::class);
282
+ $ customerData = $ customerRegistry ->retrieveByEmail ($ email );
283
+ $ token = $ this ->random ->getUniqueHash ();
284
+ $ customerData ->changeResetPasswordLinkToken ($ token );
285
+ $ customerData ->setData ('confirmation ' , 'confirmation ' );
286
+ $ customerData ->save ();
287
+
288
+ $ customerId = $ customerData ->getId ();
289
+
290
+ $ this ->resetRequest ();
291
+ $ this ->clearCookieMessagesList ();
292
+
293
+ /** @var Session $customer */
294
+ $ session = Bootstrap::getObjectManager ()->get (Session::class);
295
+ $ session ->setRpToken ($ token );
296
+ $ session ->setRpCustomerId ($ customerId );
297
+
298
+ $ this ->getRequest ()->setParam ('token ' , $ token )->setParam ('id ' , $ customerId );
299
+ $ this ->dispatch ('customer/account/createPassword ' );
300
+ $ this ->assertSessionMessages (
301
+ $ this ->equalTo ([]),
302
+ MessageInterface::TYPE_ERROR
303
+ );
304
+
305
+ $ rpTokenCreatedAt = $ this ->dateTimeFactory ->create ()
306
+ ->sub (\DateInterval::createFromDateString ('2 hour ' ))
307
+ ->format (DateTime::DATETIME_PHP_FORMAT );
308
+
309
+ $ customerSecure = $ customerRegistry ->retrieveSecureData ($ customerId );
310
+ $ customerSecure ->setRpTokenCreatedAt ($ rpTokenCreatedAt );
311
+ $ this ->customerResource ->save ($ customerData );
312
+
313
+ $ this ->getRequest ()->setParam ('token ' , $ token )->setParam ('id ' , $ customerId );
314
+ $ this ->getRequest ()->setMethod (HttpRequest::METHOD_GET );
315
+ $ this ->dispatch ('customer/account/createPassword ' );
316
+
317
+ $ this ->assertSessionMessages (
318
+ $ this ->equalTo (['Your password reset link has expired. ' ]),
319
+ MessageInterface::TYPE_ERROR
320
+ );
321
+ }
322
+
323
+ /**
324
+ * @inheritDoc
325
+ */
326
+ protected function resetRequest (): void
327
+ {
328
+ $ this ->_objectManager ->removeSharedInstance (Http::class);
329
+ $ this ->_objectManager ->removeSharedInstance (Request::class);
330
+ parent ::resetRequest ();
331
+ }
332
+
333
+ /**
334
+ * Clear cookie messages list.
335
+ *
336
+ * @return void
337
+ */
338
+ private function clearCookieMessagesList (): void
339
+ {
340
+ $ cookieManager = $ this ->_objectManager ->get (CookieManagerInterface::class);
341
+ $ jsonSerializer = $ this ->_objectManager ->get (Json::class);
342
+ $ cookieManager ->setPublicCookie (
343
+ MessagePlugin::MESSAGES_COOKIES_NAME ,
344
+ $ jsonSerializer ->serialize ([])
345
+ );
346
+ }
137
347
}
0 commit comments