IndexTest.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Controller\Adminhtml;
  7. use Magento\Customer\Api\AccountManagementInterface;
  8. use Magento\Customer\Api\AddressRepositoryInterface;
  9. use Magento\Customer\Api\CustomerRepositoryInterface;
  10. use Magento\Customer\Controller\RegistryConstants;
  11. use Magento\Customer\Model\EmailNotification;
  12. use Magento\TestFramework\Helper\Bootstrap;
  13. use Magento\Framework\App\Request\Http as HttpRequest;
  14. /**
  15. * @magentoAppArea adminhtml
  16. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  17. */
  18. class IndexTest extends \Magento\TestFramework\TestCase\AbstractBackendController
  19. {
  20. /**
  21. * Base controller URL
  22. *
  23. * @var string
  24. */
  25. protected $_baseControllerUrl;
  26. /** @var CustomerRepositoryInterface */
  27. protected $customerRepository;
  28. /** @var AddressRepositoryInterface */
  29. protected $addressRepository;
  30. /** @var AccountManagementInterface */
  31. protected $accountManagement;
  32. /** @var \Magento\Framework\Data\Form\FormKey */
  33. protected $formKey;
  34. /**@var \Magento\Customer\Helper\View */
  35. protected $customerViewHelper;
  36. /** @var \Magento\TestFramework\ObjectManager */
  37. protected $objectManager;
  38. /**
  39. * @inheritDoc
  40. */
  41. protected function setUp()
  42. {
  43. parent::setUp();
  44. $this->_baseControllerUrl = 'http://localhost/index.php/backend/customer/index/';
  45. $this->customerRepository = Bootstrap::getObjectManager()->get(
  46. \Magento\Customer\Api\CustomerRepositoryInterface::class
  47. );
  48. $this->addressRepository = Bootstrap::getObjectManager()->get(
  49. \Magento\Customer\Api\AddressRepositoryInterface::class
  50. );
  51. $this->accountManagement = Bootstrap::getObjectManager()->get(
  52. \Magento\Customer\Api\AccountManagementInterface::class
  53. );
  54. $this->formKey = Bootstrap::getObjectManager()->get(
  55. \Magento\Framework\Data\Form\FormKey::class
  56. );
  57. $this->objectManager = Bootstrap::getObjectManager();
  58. $this->customerViewHelper = $this->objectManager->get(
  59. \Magento\Customer\Helper\View::class
  60. );
  61. }
  62. /**
  63. * @inheritDoc
  64. */
  65. protected function tearDown()
  66. {
  67. /**
  68. * Unset customer data
  69. */
  70. Bootstrap::getObjectManager()->get(\Magento\Backend\Model\Session::class)->setCustomerData(null);
  71. /**
  72. * Unset messages
  73. */
  74. Bootstrap::getObjectManager()->get(\Magento\Backend\Model\Session::class)->getMessages(true);
  75. }
  76. /**
  77. * @magentoDbIsolation enabled
  78. */
  79. public function testSaveActionWithEmptyPostData()
  80. {
  81. $this->getRequest()->setPostValue([])->setMethod(HttpRequest::METHOD_POST);
  82. $this->dispatch('backend/customer/index/save');
  83. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl));
  84. }
  85. /**
  86. * @magentoDbIsolation enabled
  87. */
  88. public function testSaveActionWithInvalidFormData()
  89. {
  90. $post = ['account' => ['middlename' => 'test middlename', 'group_id' => 1]];
  91. $this->getRequest()->setPostValue($post)->setMethod(HttpRequest::METHOD_POST);
  92. $this->dispatch('backend/customer/index/save');
  93. /**
  94. * Check that errors was generated and set to session
  95. */
  96. $this->assertSessionMessages(
  97. $this->logicalNot($this->isEmpty()),
  98. \Magento\Framework\Message\MessageInterface::TYPE_ERROR
  99. );
  100. /** @var \Magento\Backend\Model\Session $session */
  101. $session = $this->objectManager->get(\Magento\Backend\Model\Session::class);
  102. /**
  103. * Check that customer data were set to session
  104. */
  105. $this->assertNotEmpty($session->getCustomerFormData());
  106. $this->assertArraySubset($post, $session->getCustomerFormData());
  107. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'new'));
  108. }
  109. /**
  110. * @magentoDataFixture Magento/Newsletter/_files/subscribers.php
  111. */
  112. public function testSaveActionExistingCustomerUnsubscribeNewsletter()
  113. {
  114. $customerId = 1;
  115. /** @var \Magento\Newsletter\Model\Subscriber $subscriber */
  116. $subscriber = $this->objectManager->get(\Magento\Newsletter\Model\SubscriberFactory::class)->create();
  117. $this->assertEmpty($subscriber->getId());
  118. $subscriber->loadByCustomerId($customerId);
  119. $this->assertNotEmpty($subscriber->getId());
  120. $this->assertEquals(1, $subscriber->getStatus());
  121. $post = [
  122. 'customer' => [
  123. 'entity_id' => $customerId,
  124. 'email' => 'customer@example.com',
  125. 'firstname' => 'test firstname',
  126. 'lastname' => 'test lastname',
  127. 'sendemail_store_id' => 1
  128. ],
  129. 'subscription' => '0'
  130. ];
  131. $this->getRequest()->setPostValue($post)->setMethod(HttpRequest::METHOD_POST);
  132. $this->getRequest()->setParam('id', 1);
  133. $this->dispatch('backend/customer/index/save');
  134. /** @var \Magento\Newsletter\Model\Subscriber $subscriber */
  135. $subscriber = $this->objectManager->get(\Magento\Newsletter\Model\SubscriberFactory::class)->create();
  136. $this->assertEmpty($subscriber->getId());
  137. $subscriber->loadByCustomerId($customerId);
  138. $this->assertNotEmpty($subscriber->getId());
  139. $this->assertEquals(3, $subscriber->getStatus());
  140. /**
  141. * Check that success message is set
  142. */
  143. $this->assertSessionMessages(
  144. $this->equalTo(['You saved the customer.']),
  145. \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
  146. );
  147. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'index/key/'));
  148. }
  149. /**
  150. * Ensure that an email is sent during save action
  151. *
  152. * @magentoConfigFixture current_store customer/account_information/change_email_template change_email_template
  153. * @magentoConfigFixture current_store customer/password/forgot_email_identity support
  154. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  155. */
  156. public function testSaveActionExistingCustomerChangeEmail()
  157. {
  158. $customerId = 1;
  159. $newEmail = 'newcustomer@example.com';
  160. $transportBuilderMock = $this->prepareEmailMock(
  161. 2,
  162. 'change_email_template',
  163. [
  164. 'name' => 'CustomerSupport',
  165. 'email' => 'support@example.com',
  166. ],
  167. $customerId,
  168. $newEmail
  169. );
  170. $this->addEmailMockToClass($transportBuilderMock, EmailNotification::class);
  171. $post = [
  172. 'customer' => [
  173. 'entity_id' => $customerId,
  174. 'middlename' => 'test middlename',
  175. 'group_id' => 1,
  176. 'website_id' => 1,
  177. 'firstname' => 'test firstname',
  178. 'lastname' => 'test lastname',
  179. 'email' => $newEmail,
  180. 'new_password' => 'auto',
  181. 'sendemail_store_id' => '1',
  182. 'sendemail' => '1',
  183. 'created_at' => '2000-01-01 00:00:00',
  184. 'default_shipping' => '_item1',
  185. 'default_billing' => 1,
  186. ]
  187. ];
  188. $this->getRequest()->setPostValue($post)->setMethod(HttpRequest::METHOD_POST);
  189. $this->getRequest()->setParam('id', 1);
  190. $this->dispatch('backend/customer/index/save');
  191. /**
  192. * Check that no errors were generated and set to session
  193. */
  194. $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR);
  195. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'index/key/'));
  196. }
  197. /**
  198. * Ensure that an email is sent during inlineEdit action
  199. *
  200. * @magentoConfigFixture current_store customer/account_information/change_email_template change_email_template
  201. * @magentoConfigFixture current_store customer/password/forgot_email_identity support
  202. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  203. */
  204. public function testInlineEditChangeEmail()
  205. {
  206. $customerId = 1;
  207. $newEmail = 'newcustomer@example.com';
  208. $transportBuilderMock = $this->prepareEmailMock(
  209. 2,
  210. 'change_email_template',
  211. [
  212. 'name' => 'CustomerSupport',
  213. 'email' => 'support@example.com',
  214. ],
  215. $customerId,
  216. $newEmail
  217. );
  218. $this->addEmailMockToClass($transportBuilderMock, EmailNotification::class);
  219. $post = [
  220. 'items' => [
  221. $customerId => [
  222. 'middlename' => 'test middlename',
  223. 'group_id' => 1,
  224. 'website_id' => 1,
  225. 'firstname' => 'test firstname',
  226. 'lastname' => 'test lastname',
  227. 'email' => $newEmail,
  228. 'password' => 'password',
  229. ],
  230. ]
  231. ];
  232. $this->getRequest()->setParam('ajax', true)->setParam('isAjax', true);
  233. $this->getRequest()->setPostValue($post)->setMethod(HttpRequest::METHOD_POST);
  234. $this->getRequest()->setParam('id', 1);
  235. $this->dispatch('backend/customer/index/inlineEdit');
  236. /**
  237. * Check that no errors were generated and set to session
  238. */
  239. $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR);
  240. }
  241. /**
  242. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  243. */
  244. public function testSaveActionCoreException()
  245. {
  246. $post = [
  247. 'customer' => [
  248. 'middlename' => 'test middlename',
  249. 'group_id' => 1,
  250. 'website_id' => 1,
  251. 'firstname' => 'test firstname',
  252. 'lastname' => 'test lastname',
  253. 'email' => 'customer@example.com',
  254. 'password' => 'password',
  255. ],
  256. ];
  257. $this->getRequest()->setPostValue($post)->setMethod(HttpRequest::METHOD_POST);
  258. $this->dispatch('backend/customer/index/save');
  259. /*
  260. * Check that error message is set
  261. */
  262. $this->assertSessionMessages(
  263. $this->equalTo(['A customer with the same email address already exists in an associated website.']),
  264. \Magento\Framework\Message\MessageInterface::TYPE_ERROR
  265. );
  266. $this->assertArraySubset(
  267. $post,
  268. Bootstrap::getObjectManager()->get(\Magento\Backend\Model\Session::class)->getCustomerFormData()
  269. );
  270. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'new/key/'));
  271. }
  272. /**
  273. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  274. */
  275. public function testEditAction()
  276. {
  277. $this->getRequest()->setParam('id', 1);
  278. $this->dispatch('backend/customer/index/edit');
  279. $body = $this->getResponse()->getBody();
  280. // verify
  281. $this->assertContains('<h1 class="page-title">test firstname test lastname</h1>', $body);
  282. }
  283. /**
  284. * Test new customer form page.
  285. */
  286. public function testNewAction()
  287. {
  288. $this->dispatch('backend/customer/index/edit');
  289. $body = $this->getResponse()->getBody();
  290. // verify
  291. $this->assertContains('<h1 class="page-title">New Customer</h1>', $body);
  292. }
  293. /**
  294. * Test the editing of a new customer that has not been saved but the page has been reloaded
  295. */
  296. public function te1stNewActionWithCustomerData()
  297. {
  298. $customerData = [
  299. 'customer_id' => 0,
  300. 'customer' => [
  301. 'created_in' => false,
  302. 'disable_auto_group_change' => false,
  303. 'email' => false,
  304. 'firstname' => false,
  305. 'group_id' => false,
  306. 'lastname' => false,
  307. 'website_id' => false,
  308. 'customer_address' => [],
  309. ],
  310. ];
  311. $context = Bootstrap::getObjectManager()->get(\Magento\Backend\Block\Template\Context::class);
  312. $context->getBackendSession()->setCustomerData($customerData);
  313. $this->testNewAction();
  314. }
  315. /**
  316. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  317. */
  318. public function testDeleteAction()
  319. {
  320. $this->getRequest()->setParam('id', 1);
  321. $this->getRequest()->setParam('form_key', $this->formKey->getFormKey());
  322. $this->getRequest()->setMethod(\Zend\Http\Request::METHOD_POST);
  323. $this->dispatch('backend/customer/index/delete');
  324. $this->assertRedirect($this->stringContains('customer/index'));
  325. $this->assertSessionMessages(
  326. $this->equalTo(['You deleted the customer.']),
  327. \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
  328. );
  329. }
  330. /**
  331. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  332. */
  333. public function testNotExistingCustomerDeleteAction()
  334. {
  335. $this->getRequest()->setParam('id', 2);
  336. $this->getRequest()->setParam('form_key', $this->formKey->getFormKey());
  337. $this->getRequest()->setMethod(\Zend\Http\Request::METHOD_POST);
  338. $this->dispatch('backend/customer/index/delete');
  339. $this->assertRedirect($this->stringContains('customer/index'));
  340. $this->assertSessionMessages(
  341. $this->equalTo(['No such entity with customerId = 2']),
  342. \Magento\Framework\Message\MessageInterface::TYPE_ERROR
  343. );
  344. }
  345. /**
  346. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  347. */
  348. public function testCartAction()
  349. {
  350. $this->getRequest()->setParam('id', 1)->setParam('website_id', 1)->setPostValue('delete', 1);
  351. $this->dispatch('backend/customer/index/cart');
  352. $body = $this->getResponse()->getBody();
  353. $this->assertContains('<div id="customer_cart_grid1"', $body);
  354. }
  355. /**
  356. * @magentoDataFixture Magento/Customer/_files/customer_sample.php
  357. */
  358. public function testProductReviewsAction()
  359. {
  360. $this->getRequest()->setParam('id', 1);
  361. $this->dispatch('backend/customer/index/productReviews');
  362. $body = $this->getResponse()->getBody();
  363. $this->assertContains('<div id="reviwGrid"', $body);
  364. }
  365. /**
  366. * @magentoDataFixture Magento/Customer/_files/customer.php
  367. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  368. */
  369. public function testValidateCustomerWithAddressSuccess()
  370. {
  371. $customerData = [
  372. 'customer' => [
  373. 'entity_id' => '1',
  374. 'middlename' => 'new middlename',
  375. 'group_id' => 1,
  376. 'website_id' => 1,
  377. 'firstname' => 'new firstname',
  378. 'lastname' => 'new lastname',
  379. 'email' => 'example@domain.com',
  380. 'default_shipping' => '_item1',
  381. 'new_password' => 'auto',
  382. 'sendemail_store_id' => '1',
  383. 'sendemail' => '1',
  384. ],
  385. 'address' => [
  386. '_item1' => [
  387. 'firstname' => 'update firstname',
  388. 'lastname' => 'update lastname',
  389. 'street' => ['update street'],
  390. 'city' => 'update city',
  391. 'country_id' => 'US',
  392. 'region_id' => 10,
  393. 'postcode' => '01001',
  394. 'telephone' => '+7000000001',
  395. ],
  396. '_template_' => [
  397. 'firstname' => '',
  398. 'lastname' => '',
  399. 'street' => [],
  400. 'city' => '',
  401. 'country_id' => 'US',
  402. 'postcode' => '',
  403. 'telephone' => '',
  404. ],
  405. ],
  406. ];
  407. /**
  408. * set customer data
  409. */
  410. $this->getRequest()->setParams($customerData)->setMethod(HttpRequest::METHOD_POST);
  411. $this->dispatch('backend/customer/index/validate');
  412. $body = $this->getResponse()->getBody();
  413. /**
  414. * Check that no errors were generated and set to session
  415. */
  416. $this->assertSessionMessages($this->isEmpty(), \Magento\Framework\Message\MessageInterface::TYPE_ERROR);
  417. $this->assertEquals('{"error":0}', $body);
  418. }
  419. /**
  420. * @magentoDbIsolation enabled
  421. */
  422. public function testResetPasswordActionNoCustomerId()
  423. {
  424. // No customer ID in post, will just get redirected to base
  425. $this->getRequest()->setMethod(HttpRequest::METHOD_GET);
  426. $this->dispatch('backend/customer/index/resetPassword');
  427. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl));
  428. }
  429. /**
  430. * @magentoDbIsolation enabled
  431. */
  432. public function testResetPasswordActionBadCustomerId()
  433. {
  434. // Bad customer ID in post, will just get redirected to base
  435. $this->getRequest()->setMethod(HttpRequest::METHOD_GET);
  436. $this->getRequest()->setPostValue(['customer_id' => '789']);
  437. $this->dispatch('backend/customer/index/resetPassword');
  438. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl));
  439. }
  440. /**
  441. * @magentoDataFixture Magento/Customer/_files/customer.php
  442. */
  443. public function testResetPasswordActionSuccess()
  444. {
  445. $this->getRequest()->setPostValue(['customer_id' => '1']);
  446. $this->getRequest()->setMethod(HttpRequest::METHOD_GET);
  447. $this->dispatch('backend/customer/index/resetPassword');
  448. $this->assertSessionMessages(
  449. $this->equalTo(['The customer will receive an email with a link to reset password.']),
  450. \Magento\Framework\Message\MessageInterface::TYPE_SUCCESS
  451. );
  452. $this->assertRedirect($this->stringStartsWith($this->_baseControllerUrl . 'edit'));
  453. }
  454. /**
  455. * Prepare email mock to test emails.
  456. *
  457. * @param int $occurrenceNumber
  458. * @param string $templateId
  459. * @param array $sender
  460. * @param int $customerId
  461. * @param string|null $newEmail
  462. * @return \PHPUnit_Framework_MockObject_MockObject
  463. * @magentoDataFixture Magento/Customer/_files/customer.php
  464. */
  465. protected function prepareEmailMock(
  466. int $occurrenceNumber,
  467. string $templateId,
  468. array $sender,
  469. int $customerId,
  470. $newEmail = null
  471. ) : \PHPUnit_Framework_MockObject_MockObject {
  472. $area = \Magento\Framework\App\Area::AREA_FRONTEND;
  473. $customer = $this->customerRepository->getById($customerId);
  474. $storeId = $customer->getStoreId();
  475. $name = $this->customerViewHelper->getCustomerName($customer);
  476. $transportMock = $this->getMockBuilder(\Magento\Framework\Mail\TransportInterface::class)
  477. ->setMethods(['sendMessage'])
  478. ->getMockForAbstractClass();
  479. $transportMock->expects($this->exactly($occurrenceNumber))
  480. ->method('sendMessage');
  481. $transportBuilderMock = $this->getMockBuilder(\Magento\Framework\Mail\Template\TransportBuilder::class)
  482. ->disableOriginalConstructor()
  483. ->setMethods(
  484. [
  485. 'addTo',
  486. 'setFrom',
  487. 'setTemplateIdentifier',
  488. 'setTemplateVars',
  489. 'setTemplateOptions',
  490. 'getTransport',
  491. ]
  492. )
  493. ->getMock();
  494. $transportBuilderMock->method('setTemplateIdentifier')
  495. ->with($templateId)
  496. ->willReturnSelf();
  497. $transportBuilderMock->method('setTemplateOptions')
  498. ->with(['area' => $area, 'store' => $storeId])
  499. ->willReturnSelf();
  500. $transportBuilderMock->method('setTemplateVars')
  501. ->willReturnSelf();
  502. $transportBuilderMock->method('setFrom')
  503. ->with($sender)
  504. ->willReturnSelf();
  505. $transportBuilderMock->method('addTo')
  506. ->with($this->logicalOr($customer->getEmail(), $newEmail), $name)
  507. ->willReturnSelf();
  508. $transportBuilderMock->expects($this->exactly($occurrenceNumber))
  509. ->method('getTransport')
  510. ->willReturn($transportMock);
  511. return $transportBuilderMock;
  512. }
  513. /**
  514. * @param \PHPUnit_Framework_MockObject_MockObject $transportBuilderMock
  515. * @param string $className
  516. */
  517. protected function addEmailMockToClass(
  518. \PHPUnit_Framework_MockObject_MockObject $transportBuilderMock,
  519. $className
  520. ) {
  521. $mocked = $this->_objectManager->create(
  522. $className,
  523. ['transportBuilder' => $transportBuilderMock]
  524. );
  525. $this->_objectManager->addSharedInstance(
  526. $mocked,
  527. $className
  528. );
  529. }
  530. }