LoginPostTest.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Test\Unit\Controller\Account;
  7. use Magento\Customer\Api\AccountManagementInterface;
  8. use Magento\Customer\Controller\Account\LoginPost;
  9. use Magento\Customer\Model\Account\Redirect as AccountRedirect;
  10. use Magento\Customer\Model\Session;
  11. use Magento\Customer\Model\Url;
  12. use Magento\Framework\App\Action\Context;
  13. use Magento\Framework\App\Request\Http;
  14. use Magento\Framework\Controller\Result\Redirect;
  15. /**
  16. * Test customer account controller
  17. *
  18. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  19. */
  20. class LoginPostTest extends \PHPUnit\Framework\TestCase
  21. {
  22. /**
  23. * @var LoginPost
  24. */
  25. protected $controller;
  26. /**
  27. * @var Context | \PHPUnit_Framework_MockObject_MockObject
  28. */
  29. protected $context;
  30. /**
  31. * @var Session | \PHPUnit_Framework_MockObject_MockObject
  32. */
  33. protected $session;
  34. /**
  35. * @var AccountManagementInterface | \PHPUnit_Framework_MockObject_MockObject
  36. */
  37. protected $accountManagement;
  38. /**
  39. * @var Url | \PHPUnit_Framework_MockObject_MockObject
  40. */
  41. protected $url;
  42. /**
  43. * @var \Magento\Framework\Data\Form\FormKey\Validator | \PHPUnit_Framework_MockObject_MockObject
  44. */
  45. protected $formkeyValidator;
  46. /**
  47. * @var AccountRedirect | \PHPUnit_Framework_MockObject_MockObject
  48. */
  49. protected $accountRedirect;
  50. /**
  51. * @var Http | \PHPUnit_Framework_MockObject_MockObject
  52. */
  53. protected $request;
  54. /**
  55. * @var Redirect | \PHPUnit_Framework_MockObject_MockObject
  56. */
  57. protected $resultRedirect;
  58. /**
  59. * @var \PHPUnit_Framework_MockObject_MockObject
  60. */
  61. protected $redirectFactory;
  62. /**
  63. * @var \PHPUnit_Framework_MockObject_MockObject
  64. */
  65. protected $redirect;
  66. /**
  67. * @var \Magento\Framework\Message\ManagerInterface | \PHPUnit_Framework_MockObject_MockObject
  68. */
  69. protected $messageManager;
  70. /**
  71. * @var \Magento\Framework\App\Config\ScopeConfigInterface | \PHPUnit_Framework_MockObject_MockObject
  72. */
  73. protected $scopeConfig;
  74. protected function setUp()
  75. {
  76. $this->prepareContext();
  77. $this->session = $this->getMockBuilder(\Magento\Customer\Model\Session::class)
  78. ->disableOriginalConstructor()
  79. ->setMethods([
  80. 'isLoggedIn',
  81. 'setCustomerDataAsLoggedIn',
  82. 'regenerateId',
  83. 'setUsername',
  84. ])
  85. ->getMock();
  86. $this->accountManagement = $this->getMockBuilder(\Magento\Customer\Api\AccountManagementInterface::class)
  87. ->getMockForAbstractClass();
  88. $this->url = $this->getMockBuilder(\Magento\Customer\Model\Url::class)
  89. ->disableOriginalConstructor()
  90. ->getMock();
  91. $this->formkeyValidator = $this->getMockBuilder(\Magento\Framework\Data\Form\FormKey\Validator::class)
  92. ->disableOriginalConstructor()
  93. ->getMock();
  94. $this->accountRedirect = $this->getMockBuilder(\Magento\Customer\Model\Account\Redirect::class)
  95. ->disableOriginalConstructor()
  96. ->getMock();
  97. $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
  98. ->getMockForAbstractClass();
  99. $this->controller = new LoginPost(
  100. $this->context,
  101. $this->session,
  102. $this->accountManagement,
  103. $this->url,
  104. $this->formkeyValidator,
  105. $this->accountRedirect
  106. );
  107. $reflection = new \ReflectionClass(get_class($this->controller));
  108. $reflectionProperty = $reflection->getProperty('scopeConfig');
  109. $reflectionProperty->setAccessible(true);
  110. $reflectionProperty->setValue($this->controller, $this->scopeConfig);
  111. }
  112. /**
  113. * @param boolean $isLoggedIn
  114. * @param boolean $isValidFormKey
  115. * @dataProvider invalidFormKeyDataProvider
  116. */
  117. public function testExecuteInvalidFormKey(
  118. $isLoggedIn,
  119. $isValidFormKey
  120. ) {
  121. $this->session->expects($this->once())
  122. ->method('isLoggedIn')
  123. ->willReturn($isLoggedIn);
  124. $this->formkeyValidator->expects($this->any())
  125. ->method('validate')
  126. ->with($this->request)
  127. ->willReturn($isValidFormKey);
  128. $this->resultRedirect->expects($this->once())
  129. ->method('setPath')
  130. ->with('*/*/')
  131. ->willReturnSelf();
  132. $this->assertSame($this->resultRedirect, $this->controller->execute());
  133. }
  134. /**
  135. * @return array
  136. */
  137. public function invalidFormKeyDataProvider()
  138. {
  139. return [
  140. [
  141. 'isLoggedIn' => true,
  142. 'isValidFormKey' => false,
  143. ],
  144. [
  145. 'isLoggedIn' => false,
  146. 'isValidFormKey' => false,
  147. ],
  148. [
  149. 'isLoggedIn' => true,
  150. 'isValidFormKey' => true,
  151. ],
  152. ];
  153. }
  154. public function testExecuteNoPostData()
  155. {
  156. $this->session->expects($this->once())
  157. ->method('isLoggedIn')
  158. ->willReturn(false);
  159. $this->formkeyValidator->expects($this->once())
  160. ->method('validate')
  161. ->with($this->request)
  162. ->willReturn(true);
  163. $this->request->expects($this->once())
  164. ->method('isPost')
  165. ->willReturn(null);
  166. $this->accountRedirect->expects($this->once())
  167. ->method('getRedirect')
  168. ->willReturn($this->resultRedirect);
  169. $this->assertSame($this->resultRedirect, $this->controller->execute());
  170. }
  171. public function testExecuteEmptyLoginData()
  172. {
  173. $this->session->expects($this->once())
  174. ->method('isLoggedIn')
  175. ->willReturn(false);
  176. $this->formkeyValidator->expects($this->once())
  177. ->method('validate')
  178. ->with($this->request)
  179. ->willReturn(true);
  180. $this->request->expects($this->once())
  181. ->method('isPost')
  182. ->willReturn(true);
  183. $this->request->expects($this->once())
  184. ->method('getPost')
  185. ->with('login')
  186. ->willReturn([]);
  187. $this->messageManager->expects($this->once())
  188. ->method('addError')
  189. ->with(__('A login and a password are required.'))
  190. ->willReturnSelf();
  191. $this->accountRedirect->expects($this->once())
  192. ->method('getRedirect')
  193. ->willReturn($this->resultRedirect);
  194. $this->assertSame($this->resultRedirect, $this->controller->execute());
  195. }
  196. public function testExecuteSuccessCustomRedirect()
  197. {
  198. $username = 'user1';
  199. $password = 'pass1';
  200. $this->session->expects($this->once())
  201. ->method('isLoggedIn')
  202. ->willReturn(false);
  203. $this->formkeyValidator->expects($this->once())
  204. ->method('validate')
  205. ->with($this->request)
  206. ->willReturn(true);
  207. $this->request->expects($this->once())
  208. ->method('isPost')
  209. ->willReturn(true);
  210. $this->request->expects($this->once())
  211. ->method('getPost')
  212. ->with('login')
  213. ->willReturn([
  214. 'username' => $username,
  215. 'password' => $password,
  216. ]);
  217. $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
  218. ->getMockForAbstractClass();
  219. $this->scopeConfig->expects($this->once())
  220. ->method('getValue')
  221. ->with('customer/startup/redirect_dashboard')
  222. ->willReturn(0);
  223. $cookieUrl = 'someUrl1';
  224. $returnUrl = 'someUrl2';
  225. $this->accountRedirect->expects($this->once())
  226. ->method('getRedirectCookie')
  227. ->willReturn($cookieUrl);
  228. $this->accountRedirect->expects($this->once())
  229. ->method('clearRedirectCookie');
  230. $this->redirect->expects($this->once())
  231. ->method('success')
  232. ->with($cookieUrl)
  233. ->willReturn($returnUrl);
  234. $this->resultRedirect->expects($this->once())
  235. ->method('setUrl')
  236. ->with($returnUrl);
  237. $this->accountManagement->expects($this->once())
  238. ->method('authenticate')
  239. ->with($username, $password)
  240. ->willReturn($customerMock);
  241. $this->session->expects($this->once())
  242. ->method('setCustomerDataAsLoggedIn')
  243. ->with($customerMock)
  244. ->willReturnSelf();
  245. $this->session->expects($this->once())
  246. ->method('regenerateId')
  247. ->willReturnSelf();
  248. $this->accountRedirect->expects($this->never())
  249. ->method('getRedirect')
  250. ->willReturn($this->resultRedirect);
  251. $cookieMetadataManager = $this->getMockBuilder(\Magento\Framework\Stdlib\Cookie\PhpCookieManager::class)
  252. ->disableOriginalConstructor()
  253. ->getMock();
  254. $cookieMetadataManager->expects($this->once())
  255. ->method('getCookie')
  256. ->with('mage-cache-sessid')
  257. ->willReturn(false);
  258. $refClass = new \ReflectionClass(LoginPost::class);
  259. $refProperty = $refClass->getProperty('cookieMetadataManager');
  260. $refProperty->setAccessible(true);
  261. $refProperty->setValue($this->controller, $cookieMetadataManager);
  262. $this->assertSame($this->resultRedirect, $this->controller->execute());
  263. }
  264. public function testExecuteSuccess()
  265. {
  266. $username = 'user1';
  267. $password = 'pass1';
  268. $this->session->expects($this->once())
  269. ->method('isLoggedIn')
  270. ->willReturn(false);
  271. $this->formkeyValidator->expects($this->once())
  272. ->method('validate')
  273. ->with($this->request)
  274. ->willReturn(true);
  275. $this->request->expects($this->once())
  276. ->method('isPost')
  277. ->willReturn(true);
  278. $this->request->expects($this->once())
  279. ->method('getPost')
  280. ->with('login')
  281. ->willReturn([
  282. 'username' => $username,
  283. 'password' => $password,
  284. ]);
  285. $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
  286. ->getMockForAbstractClass();
  287. $this->scopeConfig->expects($this->once())
  288. ->method('getValue')
  289. ->with('customer/startup/redirect_dashboard')
  290. ->willReturn(1);
  291. $this->accountManagement->expects($this->once())
  292. ->method('authenticate')
  293. ->with($username, $password)
  294. ->willReturn($customerMock);
  295. $this->session->expects($this->once())
  296. ->method('setCustomerDataAsLoggedIn')
  297. ->with($customerMock)
  298. ->willReturnSelf();
  299. $this->session->expects($this->once())
  300. ->method('regenerateId')
  301. ->willReturnSelf();
  302. $this->accountRedirect->expects($this->once())
  303. ->method('getRedirect')
  304. ->willReturn($this->resultRedirect);
  305. $cookieMetadataManager = $this->getMockBuilder(\Magento\Framework\Stdlib\Cookie\PhpCookieManager::class)
  306. ->disableOriginalConstructor()
  307. ->getMock();
  308. $cookieMetadataManager->expects($this->once())
  309. ->method('getCookie')
  310. ->with('mage-cache-sessid')
  311. ->willReturn(true);
  312. $cookieMetadataFactory = $this->getMockBuilder(\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory::class)
  313. ->disableOriginalConstructor()
  314. ->getMock();
  315. $cookieMetadata = $this->getMockBuilder(\Magento\Framework\Stdlib\Cookie\CookieMetadata::class)
  316. ->disableOriginalConstructor()
  317. ->getMock();
  318. $cookieMetadataFactory->expects($this->once())
  319. ->method('createCookieMetadata')
  320. ->willReturn($cookieMetadata);
  321. $cookieMetadata->expects($this->once())
  322. ->method('setPath')
  323. ->with('/');
  324. $cookieMetadataManager->expects($this->once())
  325. ->method('deleteCookie')
  326. ->with('mage-cache-sessid', $cookieMetadata);
  327. $refClass = new \ReflectionClass(LoginPost::class);
  328. $cookieMetadataManagerProperty = $refClass->getProperty('cookieMetadataManager');
  329. $cookieMetadataManagerProperty->setAccessible(true);
  330. $cookieMetadataManagerProperty->setValue($this->controller, $cookieMetadataManager);
  331. $cookieMetadataFactoryProperty = $refClass->getProperty('cookieMetadataFactory');
  332. $cookieMetadataFactoryProperty->setAccessible(true);
  333. $cookieMetadataFactoryProperty->setValue($this->controller, $cookieMetadataFactory);
  334. $this->assertSame($this->resultRedirect, $this->controller->execute());
  335. }
  336. /**
  337. * @param array $exceptionData
  338. *
  339. * @dataProvider exceptionDataProvider
  340. */
  341. public function testExecuteWithException(
  342. $exceptionData
  343. ) {
  344. $username = 'user1';
  345. $password = 'pass1';
  346. $this->session->expects($this->once())
  347. ->method('isLoggedIn')
  348. ->willReturn(false);
  349. $this->formkeyValidator->expects($this->once())
  350. ->method('validate')
  351. ->with($this->request)
  352. ->willReturn(true);
  353. $this->request->expects($this->once())
  354. ->method('isPost')
  355. ->willReturn(true);
  356. $this->request->expects($this->once())
  357. ->method('getPost')
  358. ->with('login')
  359. ->willReturn([
  360. 'username' => $username,
  361. 'password' => $password,
  362. ]);
  363. $exception = new $exceptionData['exception'](__($exceptionData['message']));
  364. $this->accountManagement->expects($this->once())
  365. ->method('authenticate')
  366. ->with($username, $password)
  367. ->willThrowException($exception);
  368. $this->mockExceptions($exceptionData['exception'], $username);
  369. $this->accountRedirect->expects($this->once())
  370. ->method('getRedirect')
  371. ->willReturn($this->resultRedirect);
  372. $this->assertSame($this->resultRedirect, $this->controller->execute());
  373. }
  374. /**
  375. * @return array
  376. */
  377. public function exceptionDataProvider()
  378. {
  379. return [
  380. [
  381. [
  382. 'message' => 'EmailNotConfirmedException',
  383. 'exception' => \Magento\Framework\Exception\EmailNotConfirmedException::class,
  384. ],
  385. ],
  386. [
  387. [
  388. 'message' => 'AuthenticationException',
  389. 'exception' => \Magento\Framework\Exception\AuthenticationException::class,
  390. ],
  391. ],
  392. [
  393. [
  394. 'message' => 'Exception',
  395. 'exception' => '\Exception',
  396. ],
  397. ],
  398. [
  399. [
  400. 'message' => 'UserLockedException',
  401. 'exception' => \Magento\Framework\Exception\State\UserLockedException::class,
  402. ],
  403. ],
  404. ];
  405. }
  406. protected function prepareContext()
  407. {
  408. $this->context = $this->getMockBuilder(\Magento\Framework\App\Action\Context::class)
  409. ->disableOriginalConstructor()
  410. ->getMock();
  411. $this->request = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
  412. ->disableOriginalConstructor()
  413. ->setMethods([
  414. 'isPost',
  415. 'getPost',
  416. ])
  417. ->getMock();
  418. $this->resultRedirect = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class)
  419. ->disableOriginalConstructor()
  420. ->getMock();
  421. $this->messageManager = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)
  422. ->disableOriginalConstructor()
  423. ->getMock();
  424. $this->redirectFactory = $this->getMockBuilder(\Magento\Framework\Controller\Result\RedirectFactory::class)
  425. ->disableOriginalConstructor()
  426. ->getMock();
  427. $this->redirect = $this->getMockBuilder(\Magento\Framework\App\Response\RedirectInterface::class)
  428. ->getMock();
  429. $this->context->expects($this->atLeastOnce())
  430. ->method('getRedirect')
  431. ->willReturn($this->redirect);
  432. $this->redirectFactory->expects($this->any())
  433. ->method('create')
  434. ->willReturn($this->resultRedirect);
  435. $this->context->expects($this->any())
  436. ->method('getRequest')
  437. ->willReturn($this->request);
  438. $this->context->expects($this->any())
  439. ->method('getResultRedirectFactory')
  440. ->willReturn($this->redirectFactory);
  441. $this->context->expects($this->any())
  442. ->method('getMessageManager')
  443. ->willReturn($this->messageManager);
  444. }
  445. /**
  446. * @param string $exception
  447. * @param string $username
  448. * @return void
  449. */
  450. protected function mockExceptions($exception, $username)
  451. {
  452. $url = 'url1';
  453. switch ($exception) {
  454. case \Magento\Framework\Exception\EmailNotConfirmedException::class:
  455. $this->url->expects($this->once())
  456. ->method('getEmailConfirmationUrl')
  457. ->with($username)
  458. ->willReturn($url);
  459. $message = __(
  460. 'This account is not confirmed.' .
  461. ' <a href="%1">Click here</a> to resend confirmation email.',
  462. $url
  463. );
  464. $this->messageManager->expects($this->once())
  465. ->method('addError')
  466. ->with($message)
  467. ->willReturnSelf();
  468. $this->session->expects($this->once())
  469. ->method('setUsername')
  470. ->with($username)
  471. ->willReturnSelf();
  472. break;
  473. case \Magento\Framework\Exception\AuthenticationException::class:
  474. $this->messageManager->expects($this->once())
  475. ->method('addError')
  476. ->with(
  477. __(
  478. 'The account sign-in was incorrect or your account is disabled temporarily. '
  479. . 'Please wait and try again later.'
  480. )
  481. )
  482. ->willReturnSelf();
  483. $this->session->expects($this->once())
  484. ->method('setUsername')
  485. ->with($username)
  486. ->willReturnSelf();
  487. break;
  488. case '\Exception':
  489. $this->messageManager->expects($this->once())
  490. ->method('addError')
  491. ->with(__('An unspecified error occurred. Please contact us for assistance.'))
  492. ->willReturnSelf();
  493. break;
  494. case \Magento\Framework\Exception\State\UserLockedException::class:
  495. $message = __(
  496. 'The account sign-in was incorrect or your account is disabled temporarily. '
  497. . 'Please wait and try again later.'
  498. );
  499. $this->messageManager->expects($this->once())
  500. ->method('addError')
  501. ->with($message)
  502. ->willReturnSelf();
  503. $this->session->expects($this->once())
  504. ->method('setUsername')
  505. ->with($username)
  506. ->willReturnSelf();
  507. break;
  508. }
  509. }
  510. }