AccountManagementTest.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Api;
  7. use Magento\Customer\Api\Data\CustomerInterface as Customer;
  8. use Magento\Customer\Model\AccountManagement;
  9. use Magento\Framework\Exception\InputException;
  10. use Magento\Framework\Webapi\Exception as HTTPExceptionCodes;
  11. use Magento\Newsletter\Model\Subscriber;
  12. use Magento\Security\Model\Config;
  13. use Magento\TestFramework\Helper\Bootstrap;
  14. use Magento\TestFramework\Helper\Customer as CustomerHelper;
  15. use Magento\TestFramework\TestCase\WebapiAbstract;
  16. /**
  17. * Test class for Magento\Customer\Api\AccountManagementInterface
  18. *
  19. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  20. */
  21. class AccountManagementTest extends WebapiAbstract
  22. {
  23. const SERVICE_VERSION = 'V1';
  24. const SERVICE_NAME = 'customerAccountManagementV1';
  25. const RESOURCE_PATH = '/V1/customers';
  26. /**
  27. * Sample values for testing
  28. */
  29. const ATTRIBUTE_CODE = 'attribute_code';
  30. const ATTRIBUTE_VALUE = 'attribute_value';
  31. /**
  32. * @var AccountManagementInterface
  33. */
  34. private $accountManagement;
  35. /**
  36. * @var \Magento\Framework\Api\SearchCriteriaBuilder
  37. */
  38. private $searchCriteriaBuilder;
  39. /**
  40. * @var \Magento\Framework\Api\SortOrderBuilder
  41. */
  42. private $sortOrderBuilder;
  43. /**
  44. * @var \Magento\Framework\Api\Search\FilterGroupBuilder
  45. */
  46. private $filterGroupBuilder;
  47. /**
  48. * @var CustomerHelper
  49. */
  50. private $customerHelper;
  51. /**
  52. * @var array
  53. */
  54. private $currentCustomerId;
  55. /** @var Subscriber */
  56. private $subscriber;
  57. /**
  58. * @var \Magento\Framework\Reflection\DataObjectProcessor
  59. */
  60. private $dataObjectProcessor;
  61. /**
  62. * @var \Magento\Config\Model\Config
  63. */
  64. private $config;
  65. /**
  66. * @var int
  67. */
  68. private $configValue;
  69. /**
  70. * Execute per test initialization.
  71. */
  72. public function setUp()
  73. {
  74. $this->accountManagement = Bootstrap::getObjectManager()->get(
  75. \Magento\Customer\Api\AccountManagementInterface::class
  76. );
  77. $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(
  78. \Magento\Framework\Api\SearchCriteriaBuilder::class
  79. );
  80. $this->sortOrderBuilder = Bootstrap::getObjectManager()->create(
  81. \Magento\Framework\Api\SortOrderBuilder::class
  82. );
  83. $this->filterGroupBuilder = Bootstrap::getObjectManager()->create(
  84. \Magento\Framework\Api\Search\FilterGroupBuilder::class
  85. );
  86. $this->customerHelper = new CustomerHelper();
  87. $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
  88. \Magento\Framework\Reflection\DataObjectProcessor::class
  89. );
  90. $this->config = Bootstrap::getObjectManager()->create(
  91. \Magento\Config\Model\Config::class
  92. );
  93. $this->initSubscriber();
  94. if ($this->config->getConfigDataValue(
  95. Config::XML_PATH_FRONTEND_AREA .
  96. Config::XML_PATH_PASSWORD_RESET_PROTECTION_TYPE
  97. ) != 0) {
  98. $this->configValue = $this->config
  99. ->getConfigDataValue(
  100. Config::XML_PATH_FRONTEND_AREA .
  101. Config::XML_PATH_PASSWORD_RESET_PROTECTION_TYPE
  102. );
  103. $this->config->setDataByPath(
  104. Config::XML_PATH_FRONTEND_AREA . Config::XML_PATH_PASSWORD_RESET_PROTECTION_TYPE,
  105. 0
  106. );
  107. $this->config->save();
  108. }
  109. }
  110. public function tearDown()
  111. {
  112. if (!empty($this->currentCustomerId)) {
  113. foreach ($this->currentCustomerId as $customerId) {
  114. $serviceInfo = [
  115. 'rest' => [
  116. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId,
  117. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  118. ],
  119. 'soap' => [
  120. 'service' => CustomerRepositoryTest::SERVICE_NAME,
  121. 'serviceVersion' => self::SERVICE_VERSION,
  122. 'operation' => CustomerRepositoryTest::SERVICE_NAME . 'DeleteById',
  123. ],
  124. ];
  125. $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
  126. $this->assertTrue($response);
  127. }
  128. }
  129. $this->config->setDataByPath(
  130. Config::XML_PATH_FRONTEND_AREA . Config::XML_PATH_PASSWORD_RESET_PROTECTION_TYPE,
  131. $this->configValue
  132. );
  133. $this->config->save();
  134. $this->accountManagement = null;
  135. $this->subscriber = null;
  136. }
  137. private function initSubscriber()
  138. {
  139. $this->subscriber = Bootstrap::getObjectManager()->create(
  140. \Magento\Newsletter\Model\Subscriber::class
  141. );
  142. }
  143. public function testCreateCustomer()
  144. {
  145. $customerData = $this->_createCustomer();
  146. $this->assertNotNull($customerData['id']);
  147. }
  148. public function testCreateCustomerWithErrors()
  149. {
  150. $serviceInfo = [
  151. 'rest' => [
  152. 'resourcePath' => self::RESOURCE_PATH,
  153. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, ],
  154. 'soap' => [
  155. 'service' => self::SERVICE_NAME,
  156. 'serviceVersion' => self::SERVICE_VERSION,
  157. 'operation' => self::SERVICE_NAME . 'CreateAccount',
  158. ],
  159. ];
  160. $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
  161. $this->customerHelper->createSampleCustomerDataObject(),
  162. \Magento\Customer\Api\Data\CustomerInterface::class
  163. );
  164. $invalidEmail = 'invalid';
  165. $customerDataArray['email'] = $invalidEmail;
  166. $requestData = ['customer' => $customerDataArray, 'password' => CustomerHelper::PASSWORD];
  167. try {
  168. $this->_webApiCall($serviceInfo, $requestData);
  169. $this->fail('Expected exception did not occur.');
  170. } catch (\Exception $e) {
  171. if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
  172. $expectedException = new InputException();
  173. $expectedException->addError(__('"Email" is not a valid email address.'));
  174. $this->assertInstanceOf('SoapFault', $e);
  175. $this->checkSoapFault(
  176. $e,
  177. $expectedException->getRawMessage(),
  178. 'env:Sender',
  179. $expectedException->getParameters() // expected error parameters
  180. );
  181. } else {
  182. $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
  183. $exceptionData = $this->processRestExceptionResult($e);
  184. $expectedExceptionData = [
  185. 'message' => '"Email" is not a valid email address.',
  186. ];
  187. $this->assertEquals($expectedExceptionData, $exceptionData);
  188. }
  189. }
  190. }
  191. public function testCreateCustomerWithoutOptionalFields()
  192. {
  193. $serviceInfo = [
  194. 'rest' => [
  195. 'resourcePath' => self::RESOURCE_PATH,
  196. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, ],
  197. 'soap' => [
  198. 'service' => self::SERVICE_NAME,
  199. 'serviceVersion' => self::SERVICE_VERSION,
  200. 'operation' => self::SERVICE_NAME . 'CreateAccount',
  201. ],
  202. ];
  203. $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
  204. $this->customerHelper->createSampleCustomerDataObject(),
  205. \Magento\Customer\Api\Data\CustomerInterface::class
  206. );
  207. unset($customerDataArray['store_id']);
  208. unset($customerDataArray['website_id']);
  209. $requestData = ['customer' => $customerDataArray, 'password' => CustomerHelper::PASSWORD];
  210. try {
  211. $customerData = $this->_webApiCall($serviceInfo, $requestData, null, 'all');
  212. $this->assertNotNull($customerData['id']);
  213. } catch (\Exception $e) {
  214. $this->fail('Customer should be created without optional fields.');
  215. }
  216. }
  217. /**
  218. * Test customer activation when it is required
  219. *
  220. * @magentoConfigFixture default_store customer/create_account/confirm 0
  221. */
  222. public function testActivateCustomer()
  223. {
  224. $customerData = $this->_createCustomer();
  225. $this->assertNotNull($customerData[Customer::CONFIRMATION], 'Customer activation is not required');
  226. $serviceInfo = [
  227. 'rest' => [
  228. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::EMAIL] . '/activate',
  229. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  230. ],
  231. 'soap' => [
  232. 'service' => self::SERVICE_NAME,
  233. 'serviceVersion' => self::SERVICE_VERSION,
  234. 'operation' => self::SERVICE_NAME . 'Activate',
  235. ],
  236. ];
  237. $requestData = [
  238. 'email' => $customerData[Customer::EMAIL],
  239. 'confirmationKey' => $customerData[Customer::CONFIRMATION],
  240. ];
  241. $result = $this->_webApiCall($serviceInfo, $requestData);
  242. $this->assertEquals($customerData[Customer::ID], $result[Customer::ID], 'Wrong customer!');
  243. $this->assertTrue(
  244. !isset($result[Customer::CONFIRMATION]) || $result[Customer::CONFIRMATION] === null,
  245. 'Customer is not activated!'
  246. );
  247. }
  248. public function testGetCustomerActivateCustomer()
  249. {
  250. $customerData = $this->_createCustomer();
  251. $serviceInfo = [
  252. 'rest' => [
  253. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::EMAIL] . '/activate',
  254. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  255. ],
  256. 'soap' => [
  257. 'service' => self::SERVICE_NAME,
  258. 'serviceVersion' => self::SERVICE_VERSION,
  259. 'operation' => self::SERVICE_NAME . 'Activate',
  260. ],
  261. ];
  262. $requestData = [
  263. 'email' => $customerData[Customer::EMAIL],
  264. 'confirmationKey' => $customerData[Customer::CONFIRMATION],
  265. ];
  266. $customerResponseData = $this->_webApiCall($serviceInfo, $requestData);
  267. $this->assertEquals($customerData[Customer::ID], $customerResponseData[Customer::ID]);
  268. // Confirmation key is removed after confirmation
  269. $this->assertFalse(isset($customerResponseData[Customer::CONFIRMATION]));
  270. }
  271. public function testValidateResetPasswordLinkToken()
  272. {
  273. $customerData = $this->_createCustomer();
  274. /** @var \Magento\Customer\Model\Customer $customerModel */
  275. $customerModel = Bootstrap::getObjectManager()->create(\Magento\Customer\Model\CustomerFactory::class)
  276. ->create();
  277. $customerModel->load($customerData[Customer::ID]);
  278. $rpToken = 'lsdj579slkj5987slkj595lkj';
  279. $customerModel->setRpToken('lsdj579slkj5987slkj595lkj');
  280. $customerModel->setRpTokenCreatedAt(date('Y-m-d H:i:s'));
  281. $customerModel->save();
  282. $path = self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/password/resetLinkToken/' . $rpToken;
  283. $serviceInfo = [
  284. 'rest' => [
  285. 'resourcePath' => $path,
  286. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  287. ],
  288. 'soap' => [
  289. 'service' => self::SERVICE_NAME,
  290. 'serviceVersion' => self::SERVICE_VERSION,
  291. 'operation' => self::SERVICE_NAME . 'ValidateResetPasswordLinkToken',
  292. ],
  293. ];
  294. $this->_webApiCall(
  295. $serviceInfo,
  296. ['customerId' => $customerData['id'], 'resetPasswordLinkToken' => $rpToken]
  297. );
  298. }
  299. public function testValidateResetPasswordLinkTokenInvalidToken()
  300. {
  301. $customerData = $this->_createCustomer();
  302. $invalidToken = 'fjjkafjie';
  303. $path = self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/password/resetLinkToken/' . $invalidToken;
  304. $serviceInfo = [
  305. 'rest' => [
  306. 'resourcePath' => $path,
  307. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  308. ],
  309. 'soap' => [
  310. 'service' => self::SERVICE_NAME,
  311. 'serviceVersion' => self::SERVICE_VERSION,
  312. 'operation' => self::SERVICE_NAME . 'ValidateResetPasswordLinkToken',
  313. ],
  314. ];
  315. $expectedMessage = 'The password token is mismatched. Reset and try again.';
  316. try {
  317. if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
  318. $this->_webApiCall(
  319. $serviceInfo,
  320. ['customerId' => $customerData['id'], 'resetPasswordLinkToken' => 'invalid']
  321. );
  322. } else {
  323. $this->_webApiCall($serviceInfo);
  324. }
  325. $this->fail("Expected exception to be thrown.");
  326. } catch (\SoapFault $e) {
  327. $this->assertContains(
  328. $expectedMessage,
  329. $e->getMessage(),
  330. "Exception message does not match"
  331. );
  332. } catch (\Exception $e) {
  333. $errorObj = $this->processRestExceptionResult($e);
  334. $this->assertEquals($expectedMessage, $errorObj['message']);
  335. $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
  336. }
  337. }
  338. public function testInitiatePasswordMissingRequiredFields()
  339. {
  340. $this->_markTestAsRestOnly('Soap clients explicitly check for required fields based on WSDL.');
  341. $serviceInfo = [
  342. 'rest' => [
  343. 'resourcePath' => self::RESOURCE_PATH . '/password',
  344. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  345. ]
  346. ];
  347. try {
  348. $this->_webApiCall($serviceInfo);
  349. } catch (\Exception $e) {
  350. $this->assertEquals(\Magento\Framework\Webapi\Exception::HTTP_BAD_REQUEST, $e->getCode());
  351. $exceptionData = $this->processRestExceptionResult($e);
  352. $expectedExceptionData = [
  353. 'message' => 'One or more input exceptions have occurred.',
  354. 'errors' => [
  355. [
  356. 'message' => '"%fieldName" is required. Enter and try again.',
  357. 'parameters' => [
  358. 'fieldName' => 'email',
  359. ],
  360. ],
  361. [
  362. 'message' => '"%fieldName" is required. Enter and try again.',
  363. 'parameters' => [
  364. 'fieldName' => 'template',
  365. ]
  366. ],
  367. ],
  368. ];
  369. $this->assertEquals($expectedExceptionData, $exceptionData);
  370. }
  371. }
  372. public function testInitiatePasswordReset()
  373. {
  374. $customerData = $this->_createCustomer();
  375. $serviceInfo = [
  376. 'rest' => [
  377. 'resourcePath' => self::RESOURCE_PATH . '/password',
  378. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  379. ],
  380. 'soap' => [
  381. 'service' => self::SERVICE_NAME,
  382. 'serviceVersion' => self::SERVICE_VERSION,
  383. 'operation' => self::SERVICE_NAME . 'InitiatePasswordReset',
  384. ],
  385. ];
  386. $requestData = [
  387. 'email' => $customerData[Customer::EMAIL],
  388. 'template' => AccountManagement::EMAIL_RESET,
  389. 'websiteId' => $customerData[Customer::WEBSITE_ID],
  390. ];
  391. // This api doesn't return any response.
  392. // No exception or response means the request was processed successfully.
  393. // The webapi framework does not return the header information as yet. A check for HTTP 200 would be ideal here
  394. $this->_webApiCall($serviceInfo, $requestData);
  395. }
  396. public function testSendPasswordResetLinkBadEmailOrWebsite()
  397. {
  398. $serviceInfo = [
  399. 'rest' => [
  400. 'resourcePath' => self::RESOURCE_PATH . '/password',
  401. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  402. ],
  403. 'soap' => [
  404. 'service' => self::SERVICE_NAME,
  405. 'serviceVersion' => self::SERVICE_VERSION,
  406. 'operation' => self::SERVICE_NAME . 'InitiatePasswordReset',
  407. ],
  408. ];
  409. $requestData = [
  410. 'email' => 'dummy@example.com',
  411. 'template' => AccountManagement::EMAIL_RESET,
  412. 'websiteId' => 0,
  413. ];
  414. try {
  415. $this->_webApiCall($serviceInfo, $requestData);
  416. } catch (\Exception $e) {
  417. $expectedErrorParameters =
  418. [
  419. 'fieldName' => 'email',
  420. 'fieldValue' => 'dummy@example.com',
  421. 'field2Name' => 'websiteId',
  422. 'field2Value' => 0,
  423. ];
  424. if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
  425. $errorObj = $this->processRestExceptionResult($e);
  426. $this->assertEquals(
  427. 'No such entity with %fieldName = %fieldValue, %field2Name = %field2Value',
  428. $errorObj['message']
  429. );
  430. $this->assertEquals($expectedErrorParameters, $errorObj['parameters']);
  431. $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
  432. } else {
  433. $this->assertInstanceOf('SoapFault', $e);
  434. $this->checkSoapFault(
  435. $e,
  436. 'No such entity with %fieldName = %fieldValue, %field2Name = %field2Value',
  437. 'env:Sender',
  438. $expectedErrorParameters
  439. );
  440. }
  441. }
  442. }
  443. public function testGetConfirmationStatus()
  444. {
  445. $customerData = $this->_createCustomer();
  446. $serviceInfo = [
  447. 'rest' => [
  448. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/confirm',
  449. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  450. ],
  451. 'soap' => [
  452. 'service' => self::SERVICE_NAME,
  453. 'serviceVersion' => self::SERVICE_VERSION,
  454. 'operation' => self::SERVICE_NAME . 'GetConfirmationStatus',
  455. ],
  456. ];
  457. $confirmationResponse = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]);
  458. $this->assertEquals(AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED, $confirmationResponse);
  459. }
  460. public function testResendConfirmation()
  461. {
  462. $customerData = $this->_createCustomer();
  463. $serviceInfo = [
  464. 'rest' => [
  465. 'resourcePath' => self::RESOURCE_PATH . '/confirm',
  466. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  467. ],
  468. 'soap' => [
  469. 'service' => self::SERVICE_NAME,
  470. 'serviceVersion' => self::SERVICE_VERSION,
  471. 'operation' => self::SERVICE_NAME . 'ResendConfirmation',
  472. ],
  473. ];
  474. $requestData = [
  475. 'email' => $customerData[Customer::EMAIL],
  476. 'websiteId' => $customerData[Customer::WEBSITE_ID],
  477. ];
  478. // This api doesn't return any response.
  479. // No exception or response means the request was processed successfully.
  480. // The webapi framework does not return the header information as yet. A check for HTTP 200 would be ideal here
  481. $this->_webApiCall($serviceInfo, $requestData);
  482. }
  483. public function testResendConfirmationBadEmailOrWebsite()
  484. {
  485. $serviceInfo = [
  486. 'rest' => [
  487. 'resourcePath' => self::RESOURCE_PATH . '/confirm',
  488. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  489. ],
  490. 'soap' => [
  491. 'service' => self::SERVICE_NAME,
  492. 'serviceVersion' => self::SERVICE_VERSION,
  493. 'operation' => self::SERVICE_NAME . 'ResendConfirmation',
  494. ],
  495. ];
  496. $requestData = [
  497. 'email' => 'dummy@example.com',
  498. 'websiteId' => 0,
  499. ];
  500. try {
  501. $this->_webApiCall($serviceInfo, $requestData);
  502. } catch (\Exception $e) {
  503. $expectedErrorParameters =
  504. [
  505. 'fieldName' => 'email',
  506. 'fieldValue' => 'dummy@example.com',
  507. 'field2Name' => 'websiteId',
  508. 'field2Value' => 0,
  509. ];
  510. if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
  511. $errorObj = $this->processRestExceptionResult($e);
  512. $this->assertEquals(
  513. 'No such entity with %fieldName = %fieldValue, %field2Name = %field2Value',
  514. $errorObj['message']
  515. );
  516. $this->assertEquals($expectedErrorParameters, $errorObj['parameters']);
  517. $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
  518. } else {
  519. $this->assertInstanceOf('SoapFault', $e);
  520. $this->checkSoapFault(
  521. $e,
  522. 'No such entity with %fieldName = %fieldValue, %field2Name = %field2Value',
  523. 'env:Sender',
  524. $expectedErrorParameters
  525. );
  526. }
  527. }
  528. }
  529. public function testValidateCustomerData()
  530. {
  531. $customerData = $this->customerHelper->createSampleCustomerDataObject();
  532. $customerData->setFirstname(null);
  533. $customerData->setLastname(null);
  534. $serviceInfo = [
  535. 'rest' => [
  536. 'resourcePath' => self::RESOURCE_PATH . '/validate',
  537. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  538. ],
  539. 'soap' => [
  540. 'service' => self::SERVICE_NAME,
  541. 'serviceVersion' => self::SERVICE_VERSION,
  542. 'operation' => self::SERVICE_NAME . 'Validate',
  543. ],
  544. ];
  545. $customerData = $this->dataObjectProcessor->buildOutputDataArray(
  546. $customerData,
  547. \Magento\Customer\Api\Data\CustomerInterface::class
  548. );
  549. $requestData = ['customer' => $customerData];
  550. $validationResponse = $this->_webApiCall($serviceInfo, $requestData);
  551. $this->assertFalse($validationResponse['valid']);
  552. $this->assertEquals(
  553. 'The "First Name" attribute value is empty. Set the attribute and try again.',
  554. $validationResponse['messages'][0]
  555. );
  556. $this->assertEquals(
  557. 'The "Last Name" attribute value is empty. Set the attribute and try again.',
  558. $validationResponse['messages'][1]
  559. );
  560. }
  561. public function testIsReadonly()
  562. {
  563. $customerData = $this->_createCustomer();
  564. $serviceInfo = [
  565. 'rest' => [
  566. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID] . '/permissions/readonly',
  567. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  568. ],
  569. 'soap' => [
  570. 'service' => self::SERVICE_NAME,
  571. 'serviceVersion' => self::SERVICE_VERSION,
  572. 'operation' => self::SERVICE_NAME . 'IsReadonly',
  573. ],
  574. ];
  575. $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]);
  576. $this->assertFalse($response);
  577. }
  578. public function testEmailAvailable()
  579. {
  580. $customerData = $this->_createCustomer();
  581. $serviceInfo = [
  582. 'rest' => [
  583. 'resourcePath' => self::RESOURCE_PATH . '/isEmailAvailable',
  584. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  585. ],
  586. 'soap' => [
  587. 'service' => self::SERVICE_NAME,
  588. 'serviceVersion' => self::SERVICE_VERSION,
  589. 'operation' => self::SERVICE_NAME . 'IsEmailAvailable',
  590. ],
  591. ];
  592. $requestData = [
  593. 'customerEmail' => $customerData[Customer::EMAIL],
  594. 'websiteId' => $customerData[Customer::WEBSITE_ID],
  595. ];
  596. $this->assertFalse($this->_webApiCall($serviceInfo, $requestData));
  597. }
  598. public function testEmailAvailableInvalidEmail()
  599. {
  600. $serviceInfo = [
  601. 'rest' => [
  602. 'resourcePath' => self::RESOURCE_PATH . '/isEmailAvailable',
  603. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  604. ],
  605. 'soap' => [
  606. 'service' => self::SERVICE_NAME,
  607. 'serviceVersion' => self::SERVICE_VERSION,
  608. 'operation' => self::SERVICE_NAME . 'IsEmailAvailable',
  609. ],
  610. ];
  611. $requestData = [
  612. 'customerEmail' => 'invalid',
  613. 'websiteId' => 0,
  614. ];
  615. $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
  616. }
  617. /**
  618. * @magentoApiDataFixture Magento/Customer/_files/attribute_user_defined_address.php
  619. * @magentoApiDataFixture Magento/Customer/_files/attribute_user_defined_customer.php
  620. */
  621. public function testCustomAttributes()
  622. {
  623. //Sample customer data comes with the disable_auto_group_change custom attribute
  624. $customerData = $this->customerHelper->createSampleCustomerDataObject();
  625. //address attribute code from fixture
  626. $fixtureAddressAttributeCode = 'address_user_attribute';
  627. //customer attribute code from fixture
  628. $fixtureCustomerAttributeCode = 'user_attribute';
  629. //Custom Attribute Values
  630. $address1CustomAttributeValue = 'value1';
  631. $address2CustomAttributeValue = 'value2';
  632. $customerCustomAttributeValue = 'value3';
  633. $addresses = $customerData->getAddresses();
  634. $addresses[0]->setCustomAttribute($fixtureAddressAttributeCode, $address1CustomAttributeValue);
  635. $addresses[1]->setCustomAttribute($fixtureAddressAttributeCode, $address2CustomAttributeValue);
  636. $customerData->setAddresses($addresses);
  637. $customerData->setCustomAttribute($fixtureCustomerAttributeCode, $customerCustomAttributeValue);
  638. $serviceInfo = [
  639. 'rest' => [
  640. 'resourcePath' => self::RESOURCE_PATH,
  641. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  642. ],
  643. 'soap' => [
  644. 'service' => self::SERVICE_NAME,
  645. 'serviceVersion' => self::SERVICE_VERSION,
  646. 'operation' => self::SERVICE_NAME . 'CreateAccount',
  647. ],
  648. ];
  649. $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
  650. $customerData,
  651. \Magento\Customer\Api\Data\CustomerInterface::class
  652. );
  653. $requestData = ['customer' => $customerDataArray, 'password' => CustomerHelper::PASSWORD];
  654. $customerData = $this->_webApiCall($serviceInfo, $requestData);
  655. $customerId = $customerData['id'];
  656. //TODO: Fix assertions to verify custom attributes
  657. $this->assertNotNull($customerData);
  658. $serviceInfo = [
  659. 'rest' => [
  660. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId ,
  661. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  662. ],
  663. 'soap' => [
  664. 'service' => CustomerRepositoryTest::SERVICE_NAME,
  665. 'serviceVersion' => self::SERVICE_VERSION,
  666. 'operation' => CustomerRepositoryTest::SERVICE_NAME . 'DeleteById',
  667. ],
  668. ];
  669. $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
  670. $this->assertTrue($response);
  671. }
  672. /**
  673. * @magentoApiDataFixture Magento/Customer/_files/customer.php
  674. * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
  675. */
  676. public function testGetDefaultBillingAddress()
  677. {
  678. $fixtureCustomerId = 1;
  679. $serviceInfo = [
  680. 'rest' => [
  681. 'resourcePath' => self::RESOURCE_PATH . "/$fixtureCustomerId/billingAddress",
  682. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  683. ],
  684. 'soap' => [
  685. 'service' => self::SERVICE_NAME,
  686. 'serviceVersion' => self::SERVICE_VERSION,
  687. 'operation' => self::SERVICE_NAME . 'GetDefaultBillingAddress',
  688. ],
  689. ];
  690. $requestData = ['customerId' => $fixtureCustomerId];
  691. $addressData = $this->_webApiCall($serviceInfo, $requestData);
  692. $this->assertEquals(
  693. $this->getFirstFixtureAddressData(),
  694. $addressData,
  695. "Default billing address data is invalid."
  696. );
  697. }
  698. /**
  699. * @magentoApiDataFixture Magento/Customer/_files/customer.php
  700. * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php
  701. */
  702. public function testGetDefaultShippingAddress()
  703. {
  704. $fixtureCustomerId = 1;
  705. $serviceInfo = [
  706. 'rest' => [
  707. 'resourcePath' => self::RESOURCE_PATH . "/$fixtureCustomerId/shippingAddress",
  708. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  709. ],
  710. 'soap' => [
  711. 'service' => self::SERVICE_NAME,
  712. 'serviceVersion' => self::SERVICE_VERSION,
  713. 'operation' => self::SERVICE_NAME . 'GetDefaultShippingAddress',
  714. ],
  715. ];
  716. $requestData = ['customerId' => $fixtureCustomerId];
  717. $addressData = $this->_webApiCall($serviceInfo, $requestData);
  718. $this->assertEquals(
  719. $this->getFirstFixtureAddressData(),
  720. $addressData,
  721. "Default shipping address data is invalid."
  722. );
  723. }
  724. /**
  725. * @return array|bool|float|int|string
  726. */
  727. protected function _createCustomer()
  728. {
  729. $customerData = $this->customerHelper->createSampleCustomer();
  730. $this->currentCustomerId[] = $customerData['id'];
  731. return $customerData;
  732. }
  733. /**
  734. * Retrieve data of the first fixture address.
  735. *
  736. * @return array
  737. */
  738. protected function getFirstFixtureAddressData()
  739. {
  740. return [
  741. 'firstname' => 'John',
  742. 'lastname' => 'Smith',
  743. 'city' => 'CityM',
  744. 'country_id' => 'US',
  745. 'company' => 'CompanyName',
  746. 'postcode' => '75477',
  747. 'telephone' => '3468676',
  748. 'street' => ['Green str, 67'],
  749. 'id' => 1,
  750. 'default_billing' => true,
  751. 'default_shipping' => true,
  752. 'customer_id' => '1',
  753. 'region' => ['region' => 'Alabama', 'region_id' => 1, 'region_code' => 'AL'],
  754. 'region_id' => 1,
  755. ];
  756. }
  757. public function testCreateCustomerWithSubscription()
  758. {
  759. $customerData = $this->customerHelper->createSampleCustomer(
  760. ["extension_attributes" => ["is_subscribed" => true]]
  761. );
  762. $this->assertNotNull($customerData['id']);
  763. $this->subscriber->loadByCustomerId($customerData['id']);
  764. $this->assertNotNull($this->subscriber->getId());
  765. $this->assertEquals($customerData['id'], $this->subscriber->getCustomerId());
  766. }
  767. public function testUnsubscribeCustomer()
  768. {
  769. //Creating customer and subscribe
  770. $customerData = $this->customerHelper->createSampleCustomer(
  771. ["extension_attributes" => ["is_subscribed" => true]]
  772. );
  773. $this->assertNotNull($customerData['id']);
  774. $this->subscriber->loadByCustomerId($customerData['id']);
  775. $subscriptionId = $this->subscriber->getId();
  776. $this->assertNotNull($subscriptionId);
  777. $this->assertEquals($customerData['id'], $this->subscriber->getCustomerId());
  778. //Manage customer in order to unsubscribe
  779. $this->customerHelper->updateSampleCustomer(
  780. $customerData["id"],
  781. array_merge(
  782. $customerData,
  783. ["extension_attributes" => ["is_subscribed" => false]]
  784. )
  785. );
  786. $this->initSubscriber();
  787. $this->subscriber->loadByCustomerId($customerData['id']);
  788. $this->assertEquals(Subscriber::STATUS_UNSUBSCRIBED, $this->subscriber->getStatus());
  789. }
  790. }