CustomerRepositoryTest.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  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\Api\Data\AddressInterface as Address;
  9. use Magento\Framework\Api\SortOrder;
  10. use Magento\Framework\Exception\InputException;
  11. use Magento\TestFramework\Helper\Bootstrap;
  12. use Magento\TestFramework\Helper\Customer as CustomerHelper;
  13. use Magento\TestFramework\TestCase\WebapiAbstract;
  14. use Magento\Framework\Webapi\Exception as HTTPExceptionCodes;
  15. use Magento\Framework\Exception\NoSuchEntityException;
  16. /**
  17. * Test class for Magento\Customer\Api\CustomerRepositoryInterface
  18. *
  19. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  20. */
  21. class CustomerRepositoryTest extends WebapiAbstract
  22. {
  23. const SERVICE_VERSION = 'V1';
  24. const SERVICE_NAME = 'customerCustomerRepositoryV1';
  25. const RESOURCE_PATH = '/V1/customers';
  26. const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
  27. /**
  28. * Sample values for testing
  29. */
  30. const ATTRIBUTE_CODE = 'attribute_code';
  31. const ATTRIBUTE_VALUE = 'attribute_value';
  32. /**
  33. * @var CustomerRepositoryInterface
  34. */
  35. private $customerRepository;
  36. /**
  37. * @var \Magento\Framework\Api\DataObjectHelper
  38. */
  39. private $dataObjectHelper;
  40. /**
  41. * @var \Magento\Customer\Api\Data\CustomerInterfaceFactory
  42. */
  43. private $customerDataFactory;
  44. /**
  45. * @var \Magento\Framework\Api\SearchCriteriaBuilder
  46. */
  47. private $searchCriteriaBuilder;
  48. /**
  49. * @var \Magento\Framework\Api\SortOrderBuilder
  50. */
  51. private $sortOrderBuilder;
  52. /**
  53. * @var \Magento\Framework\Api\Search\FilterGroupBuilder
  54. */
  55. private $filterGroupBuilder;
  56. /**
  57. * @var \Magento\Customer\Model\CustomerRegistry
  58. */
  59. private $customerRegistry;
  60. /**
  61. * @var CustomerHelper
  62. */
  63. private $customerHelper;
  64. /**
  65. * @var array
  66. */
  67. private $currentCustomerId;
  68. /**
  69. * @var \Magento\Framework\Reflection\DataObjectProcessor
  70. */
  71. private $dataObjectProcessor;
  72. /**
  73. * Execute per test initialization.
  74. */
  75. public function setUp()
  76. {
  77. $this->customerRegistry = Bootstrap::getObjectManager()->get(
  78. \Magento\Customer\Model\CustomerRegistry::class
  79. );
  80. $this->customerRepository = Bootstrap::getObjectManager()->get(
  81. \Magento\Customer\Api\CustomerRepositoryInterface::class,
  82. ['customerRegistry' => $this->customerRegistry]
  83. );
  84. $this->dataObjectHelper = Bootstrap::getObjectManager()->create(
  85. \Magento\Framework\Api\DataObjectHelper::class
  86. );
  87. $this->customerDataFactory = Bootstrap::getObjectManager()->create(
  88. \Magento\Customer\Api\Data\CustomerInterfaceFactory::class
  89. );
  90. $this->searchCriteriaBuilder = Bootstrap::getObjectManager()->create(
  91. \Magento\Framework\Api\SearchCriteriaBuilder::class
  92. );
  93. $this->sortOrderBuilder = Bootstrap::getObjectManager()->create(
  94. \Magento\Framework\Api\SortOrderBuilder::class
  95. );
  96. $this->filterGroupBuilder = Bootstrap::getObjectManager()->create(
  97. \Magento\Framework\Api\Search\FilterGroupBuilder::class
  98. );
  99. $this->customerHelper = new CustomerHelper();
  100. $this->dataObjectProcessor = Bootstrap::getObjectManager()->create(
  101. \Magento\Framework\Reflection\DataObjectProcessor::class
  102. );
  103. }
  104. public function tearDown()
  105. {
  106. if (!empty($this->currentCustomerId)) {
  107. foreach ($this->currentCustomerId as $customerId) {
  108. $serviceInfo = [
  109. 'rest' => [
  110. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerId,
  111. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  112. ],
  113. 'soap' => [
  114. 'service' => self::SERVICE_NAME,
  115. 'serviceVersion' => self::SERVICE_VERSION,
  116. 'operation' => self::SERVICE_NAME . 'DeleteById',
  117. ],
  118. ];
  119. $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
  120. $this->assertTrue($response);
  121. }
  122. }
  123. $this->customerRepository = null;
  124. }
  125. /**
  126. * Validate update by invalid customer.
  127. *
  128. * @expectedException \Exception
  129. * @expectedExceptionMessage The consumer isn't authorized to access %resources.
  130. */
  131. public function testInvalidCustomerUpdate()
  132. {
  133. $this->_markTestAsRestOnly();
  134. //Create first customer and retrieve customer token.
  135. $firstCustomerData = $this->_createCustomer();
  136. // get customer ID token
  137. /** @var \Magento\Integration\Api\CustomerTokenServiceInterface $customerTokenService */
  138. //$customerTokenService = $this->objectManager->create(CustomerTokenServiceInterface::class);
  139. $customerTokenService = Bootstrap::getObjectManager()->create(
  140. \Magento\Integration\Api\CustomerTokenServiceInterface::class
  141. );
  142. $token = $customerTokenService->createCustomerAccessToken($firstCustomerData[Customer::EMAIL], 'test@123');
  143. //Create second customer and update lastname.
  144. $customerData = $this->_createCustomer();
  145. $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
  146. $lastName = $existingCustomerDataObject->getLastname();
  147. $customerData[Customer::LASTNAME] = $lastName . 'Updated';
  148. $newCustomerDataObject = $this->customerDataFactory->create();
  149. $this->dataObjectHelper->populateWithArray(
  150. $newCustomerDataObject,
  151. $customerData,
  152. \Magento\Customer\Api\Data\CustomerInterface::class
  153. );
  154. $serviceInfo = [
  155. 'rest' => [
  156. 'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}",
  157. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  158. 'token' => $token,
  159. ]
  160. ];
  161. $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
  162. $newCustomerDataObject,
  163. \Magento\Customer\Api\Data\CustomerInterface::class
  164. );
  165. $requestData = ['customer' => $newCustomerDataObject];
  166. $this->_webApiCall($serviceInfo, $requestData);
  167. }
  168. public function testDeleteCustomer()
  169. {
  170. $customerData = $this->_createCustomer();
  171. $this->currentCustomerId = [];
  172. $serviceInfo = [
  173. 'rest' => [
  174. 'resourcePath' => self::RESOURCE_PATH . '/' . $customerData[Customer::ID],
  175. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  176. ],
  177. 'soap' => [
  178. 'service' => self::SERVICE_NAME,
  179. 'serviceVersion' => self::SERVICE_VERSION,
  180. 'operation' => self::SERVICE_NAME . 'DeleteById',
  181. ],
  182. ];
  183. if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
  184. $response = $this->_webApiCall($serviceInfo, ['customerId' => $customerData['id']]);
  185. } else {
  186. $response = $this->_webApiCall($serviceInfo);
  187. }
  188. $this->assertTrue($response);
  189. //Verify if the customer is deleted
  190. $this->expectException(\Magento\Framework\Exception\NoSuchEntityException::class);
  191. $this->expectExceptionMessage(sprintf("No such entity with customerId = %s", $customerData[Customer::ID]));
  192. $this->_getCustomerData($customerData[Customer::ID]);
  193. }
  194. public function testDeleteCustomerInvalidCustomerId()
  195. {
  196. $invalidId = -1;
  197. $serviceInfo = [
  198. 'rest' => [
  199. 'resourcePath' => self::RESOURCE_PATH . '/' . $invalidId,
  200. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
  201. ],
  202. 'soap' => [
  203. 'service' => self::SERVICE_NAME,
  204. 'serviceVersion' => self::SERVICE_VERSION,
  205. 'operation' => self::SERVICE_NAME . 'DeleteById',
  206. ],
  207. ];
  208. $expectedMessage = 'No such entity with %fieldName = %fieldValue';
  209. try {
  210. $this->_webApiCall($serviceInfo, ['customerId' => $invalidId]);
  211. $this->fail("Expected exception");
  212. } catch (\SoapFault $e) {
  213. $this->assertContains(
  214. $expectedMessage,
  215. $e->getMessage(),
  216. "SoapFault does not contain expected message."
  217. );
  218. } catch (\Exception $e) {
  219. $errorObj = $this->processRestExceptionResult($e);
  220. $this->assertEquals($expectedMessage, $errorObj['message']);
  221. $this->assertEquals(['fieldName' => 'customerId', 'fieldValue' => $invalidId], $errorObj['parameters']);
  222. $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
  223. }
  224. }
  225. public function testUpdateCustomer()
  226. {
  227. $customerData = $this->_createCustomer();
  228. $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
  229. $lastName = $existingCustomerDataObject->getLastname();
  230. $customerData[Customer::LASTNAME] = $lastName . 'Updated';
  231. $newCustomerDataObject = $this->customerDataFactory->create();
  232. $this->dataObjectHelper->populateWithArray(
  233. $newCustomerDataObject,
  234. $customerData,
  235. \Magento\Customer\Api\Data\CustomerInterface::class
  236. );
  237. $serviceInfo = [
  238. 'rest' => [
  239. 'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}",
  240. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  241. ],
  242. 'soap' => [
  243. 'service' => self::SERVICE_NAME,
  244. 'serviceVersion' => self::SERVICE_VERSION,
  245. 'operation' => self::SERVICE_NAME . 'Save',
  246. ],
  247. ];
  248. $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
  249. $newCustomerDataObject,
  250. \Magento\Customer\Api\Data\CustomerInterface::class
  251. );
  252. $requestData = ['customer' => $newCustomerDataObject];
  253. $response = $this->_webApiCall($serviceInfo, $requestData);
  254. $this->assertTrue($response !== null);
  255. //Verify if the customer is updated
  256. $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
  257. $this->assertEquals($lastName . "Updated", $existingCustomerDataObject->getLastname());
  258. }
  259. /**
  260. * Verify expected behavior when the website id is not set
  261. */
  262. public function testUpdateCustomerNoWebsiteId()
  263. {
  264. $customerData = $this->customerHelper->createSampleCustomer();
  265. $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
  266. $lastName = $existingCustomerDataObject->getLastname();
  267. $customerData[Customer::LASTNAME] = $lastName . 'Updated';
  268. $newCustomerDataObject = $this->customerDataFactory->create();
  269. $this->dataObjectHelper->populateWithArray(
  270. $newCustomerDataObject,
  271. $customerData,
  272. \Magento\Customer\Api\Data\CustomerInterface::class
  273. );
  274. $serviceInfo = [
  275. 'rest' => [
  276. 'resourcePath' => self::RESOURCE_PATH . "/{$customerData[Customer::ID]}",
  277. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  278. ],
  279. 'soap' => [
  280. 'service' => self::SERVICE_NAME,
  281. 'serviceVersion' => self::SERVICE_VERSION,
  282. 'operation' => self::SERVICE_NAME . 'Save',
  283. ],
  284. ];
  285. $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
  286. $newCustomerDataObject,
  287. \Magento\Customer\Api\Data\CustomerInterface::class
  288. );
  289. unset($newCustomerDataObject['website_id']);
  290. $requestData = ['customer' => $newCustomerDataObject];
  291. $expectedMessage = '"Associate to Website" is a required value.';
  292. try {
  293. $this->_webApiCall($serviceInfo, $requestData);
  294. $this->fail("Expected exception.");
  295. } catch (\SoapFault $e) {
  296. $this->assertContains(
  297. $expectedMessage,
  298. $e->getMessage(),
  299. "SoapFault does not contain expected message."
  300. );
  301. } catch (\Exception $e) {
  302. $errorObj = $this->customerHelper->processRestExceptionResult($e);
  303. $this->assertEquals($expectedMessage, $errorObj['message'], 'Invalid message: "' . $e->getMessage() . '"');
  304. $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
  305. }
  306. }
  307. public function testUpdateCustomerException()
  308. {
  309. $customerData = $this->_createCustomer();
  310. $existingCustomerDataObject = $this->_getCustomerData($customerData[Customer::ID]);
  311. $lastName = $existingCustomerDataObject->getLastname();
  312. //Set non-existent id = -1
  313. $customerData[Customer::LASTNAME] = $lastName . 'Updated';
  314. $customerData[Customer::ID] = -1;
  315. $newCustomerDataObject = $this->customerDataFactory->create();
  316. $this->dataObjectHelper->populateWithArray(
  317. $newCustomerDataObject,
  318. $customerData,
  319. \Magento\Customer\Api\Data\CustomerInterface::class
  320. );
  321. $serviceInfo = [
  322. 'rest' => [
  323. 'resourcePath' => self::RESOURCE_PATH . "/-1",
  324. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  325. ],
  326. 'soap' => [
  327. 'service' => self::SERVICE_NAME,
  328. 'serviceVersion' => self::SERVICE_VERSION,
  329. 'operation' => self::SERVICE_NAME . 'Save',
  330. ],
  331. ];
  332. $newCustomerDataObject = $this->dataObjectProcessor->buildOutputDataArray(
  333. $newCustomerDataObject,
  334. \Magento\Customer\Api\Data\CustomerInterface::class
  335. );
  336. $requestData = ['customer' => $newCustomerDataObject];
  337. $expectedMessage = 'No such entity with %fieldName = %fieldValue';
  338. try {
  339. $this->_webApiCall($serviceInfo, $requestData);
  340. $this->fail("Expected exception.");
  341. } catch (\SoapFault $e) {
  342. $this->assertContains(
  343. $expectedMessage,
  344. $e->getMessage(),
  345. "SoapFault does not contain expected message."
  346. );
  347. } catch (\Exception $e) {
  348. $errorObj = $this->processRestExceptionResult($e);
  349. $this->assertEquals($expectedMessage, $errorObj['message']);
  350. $this->assertEquals(['fieldName' => 'customerId', 'fieldValue' => -1], $errorObj['parameters']);
  351. $this->assertEquals(HTTPExceptionCodes::HTTP_NOT_FOUND, $e->getCode());
  352. }
  353. }
  354. /**
  355. * Test creating a customer with absent required address fields
  356. */
  357. public function testCreateCustomerWithoutAddressRequiresException()
  358. {
  359. $customerDataArray = $this->dataObjectProcessor->buildOutputDataArray(
  360. $this->customerHelper->createSampleCustomerDataObject(),
  361. \Magento\Customer\Api\Data\CustomerInterface::class
  362. );
  363. foreach ($customerDataArray[Customer::KEY_ADDRESSES] as & $address) {
  364. $address[Address::FIRSTNAME] = null;
  365. }
  366. $serviceInfo = [
  367. 'rest' => [
  368. 'resourcePath' => self::RESOURCE_PATH,
  369. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  370. ],
  371. 'soap' => [
  372. 'service' => self::SERVICE_NAME,
  373. 'serviceVersion' => self::SERVICE_VERSION,
  374. 'operation' => self::SERVICE_NAME . 'Save',
  375. ],
  376. ];
  377. $requestData = ['customer' => $customerDataArray];
  378. try {
  379. $this->_webApiCall($serviceInfo, $requestData);
  380. $this->fail('Expected exception did not occur.');
  381. } catch (\Exception $e) {
  382. if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
  383. $expectedException = new InputException();
  384. $expectedException->addError(
  385. __(
  386. '"%fieldName" is required. Enter and try again.',
  387. ['fieldName' => Address::FIRSTNAME]
  388. )
  389. );
  390. $this->assertInstanceOf('SoapFault', $e);
  391. $this->checkSoapFault(
  392. $e,
  393. $expectedException->getRawMessage(),
  394. 'env:Sender',
  395. $expectedException->getParameters() // expected error parameters
  396. );
  397. } else {
  398. $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
  399. $exceptionData = $this->processRestExceptionResult($e);
  400. $expectedExceptionData = [
  401. 'message' => '"%fieldName" is required. Enter and try again.',
  402. 'parameters' => ['fieldName' => Address::FIRSTNAME],
  403. ];
  404. $this->assertEquals($expectedExceptionData, $exceptionData);
  405. }
  406. }
  407. try {
  408. $this->customerRegistry->retrieveByEmail(
  409. $customerDataArray[Customer::EMAIL],
  410. $customerDataArray[Customer::WEBSITE_ID]
  411. );
  412. $this->fail('An expected NoSuchEntityException was not thrown.');
  413. } catch (NoSuchEntityException $e) {
  414. $exception = NoSuchEntityException::doubleField(
  415. 'email',
  416. $customerDataArray[Customer::EMAIL],
  417. 'websiteId',
  418. $customerDataArray[Customer::WEBSITE_ID]
  419. );
  420. $this->assertEquals(
  421. $exception->getMessage(),
  422. $e->getMessage(),
  423. 'Exception message does not match expected message.'
  424. );
  425. }
  426. }
  427. /**
  428. * Test with a single filter
  429. */
  430. public function testSearchCustomers()
  431. {
  432. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  433. $customerData = $this->_createCustomer();
  434. $filter = $builder
  435. ->setField(Customer::EMAIL)
  436. ->setValue($customerData[Customer::EMAIL])
  437. ->create();
  438. $this->searchCriteriaBuilder->addFilters([$filter]);
  439. $searchData = $this->dataObjectProcessor->buildOutputDataArray(
  440. $this->searchCriteriaBuilder->create(),
  441. \Magento\Framework\Api\SearchCriteriaInterface::class
  442. );
  443. $requestData = ['searchCriteria' => $searchData];
  444. $serviceInfo = [
  445. 'rest' => [
  446. 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData),
  447. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  448. ],
  449. 'soap' => [
  450. 'service' => self::SERVICE_NAME,
  451. 'serviceVersion' => self::SERVICE_VERSION,
  452. 'operation' => self::SERVICE_NAME . 'getList',
  453. ],
  454. ];
  455. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  456. $this->assertEquals(1, $searchResults['total_count']);
  457. $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]);
  458. }
  459. /**
  460. * Test with a single filter using GET
  461. */
  462. public function testSearchCustomersUsingGET()
  463. {
  464. $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers');
  465. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  466. $customerData = $this->_createCustomer();
  467. $filter = $builder
  468. ->setField(Customer::EMAIL)
  469. ->setValue($customerData[Customer::EMAIL])
  470. ->create();
  471. $this->searchCriteriaBuilder->addFilters([$filter]);
  472. $searchData = $this->searchCriteriaBuilder->create()->__toArray();
  473. $requestData = ['searchCriteria' => $searchData];
  474. $searchQueryString = http_build_query($requestData);
  475. $serviceInfo = [
  476. 'rest' => [
  477. 'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
  478. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  479. ],
  480. ];
  481. $searchResults = $this->_webApiCall($serviceInfo);
  482. $this->assertEquals(1, $searchResults['total_count']);
  483. $this->assertEquals($customerData[Customer::ID], $searchResults['items'][0][Customer::ID]);
  484. }
  485. /**
  486. * Test with empty GET based filter
  487. */
  488. public function testSearchCustomersUsingGETEmptyFilter()
  489. {
  490. $this->_markTestAsRestOnly('Soap clients explicitly check for required fields based on WSDL.');
  491. $serviceInfo = [
  492. 'rest' => [
  493. 'resourcePath' => self::RESOURCE_PATH . '/search',
  494. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  495. ],
  496. ];
  497. try {
  498. $this->_webApiCall($serviceInfo);
  499. } catch (\Exception $e) {
  500. $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode());
  501. $exceptionData = $this->processRestExceptionResult($e);
  502. $expectedExceptionData = [
  503. 'message' => '"%fieldName" is required. Enter and try again.',
  504. 'parameters' => [
  505. 'fieldName' => 'searchCriteria'
  506. ],
  507. ];
  508. $this->assertEquals($expectedExceptionData, $exceptionData);
  509. }
  510. }
  511. /**
  512. * Test using multiple filters
  513. */
  514. public function testSearchCustomersMultipleFiltersWithSort()
  515. {
  516. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  517. $customerData1 = $this->_createCustomer();
  518. $customerData2 = $this->_createCustomer();
  519. $filter1 = $builder->setField(Customer::EMAIL)
  520. ->setValue($customerData1[Customer::EMAIL])
  521. ->create();
  522. $filter2 = $builder->setField(Customer::EMAIL)
  523. ->setValue($customerData2[Customer::EMAIL])
  524. ->create();
  525. $filter3 = $builder->setField(Customer::LASTNAME)
  526. ->setValue($customerData1[Customer::LASTNAME])
  527. ->create();
  528. $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]);
  529. $this->searchCriteriaBuilder->addFilters([$filter3]);
  530. /**@var \Magento\Framework\Api\SortOrderBuilder $sortOrderBuilder */
  531. $sortOrderBuilder = Bootstrap::getObjectManager()->create(
  532. \Magento\Framework\Api\SortOrderBuilder::class
  533. );
  534. /** @var SortOrder $sortOrder */
  535. $sortOrder = $sortOrderBuilder->setField(Customer::EMAIL)->setDirection(SortOrder::SORT_ASC)->create();
  536. $this->searchCriteriaBuilder->setSortOrders([$sortOrder]);
  537. $searchCriteria = $this->searchCriteriaBuilder->create();
  538. $searchData = $searchCriteria->__toArray();
  539. $requestData = ['searchCriteria' => $searchData];
  540. $serviceInfo = [
  541. 'rest' => [
  542. 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData),
  543. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  544. ],
  545. 'soap' => [
  546. 'service' => self::SERVICE_NAME,
  547. 'serviceVersion' => self::SERVICE_VERSION,
  548. 'operation' => self::SERVICE_NAME . 'getList',
  549. ],
  550. ];
  551. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  552. $this->assertEquals(2, $searchResults['total_count']);
  553. $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]);
  554. $this->assertEquals($customerData2[Customer::ID], $searchResults['items'][1][Customer::ID]);
  555. }
  556. /**
  557. * Test using multiple filters using GET
  558. */
  559. public function testSearchCustomersMultipleFiltersWithSortUsingGET()
  560. {
  561. $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers');
  562. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  563. $customerData1 = $this->_createCustomer();
  564. $customerData2 = $this->_createCustomer();
  565. $filter1 = $builder->setField(Customer::EMAIL)
  566. ->setValue($customerData1[Customer::EMAIL])
  567. ->create();
  568. $filter2 = $builder->setField(Customer::EMAIL)
  569. ->setValue($customerData2[Customer::EMAIL])
  570. ->create();
  571. $filter3 = $builder->setField(Customer::LASTNAME)
  572. ->setValue($customerData1[Customer::LASTNAME])
  573. ->create();
  574. $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]);
  575. $this->searchCriteriaBuilder->addFilters([$filter3]);
  576. $this->searchCriteriaBuilder->setSortOrders([Customer::EMAIL => SortOrder::SORT_ASC]);
  577. $searchCriteria = $this->searchCriteriaBuilder->create();
  578. $searchData = $searchCriteria->__toArray();
  579. $requestData = ['searchCriteria' => $searchData];
  580. $searchQueryString = http_build_query($requestData);
  581. $serviceInfo = [
  582. 'rest' => [
  583. 'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
  584. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  585. ],
  586. ];
  587. $searchResults = $this->_webApiCall($serviceInfo);
  588. $this->assertEquals(2, $searchResults['total_count']);
  589. $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]);
  590. $this->assertEquals($customerData2[Customer::ID], $searchResults['items'][1][Customer::ID]);
  591. }
  592. /**
  593. * Test and verify multiple filters using And-ed non-existent filter value
  594. */
  595. public function testSearchCustomersNonExistentMultipleFilters()
  596. {
  597. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  598. $customerData1 = $this->_createCustomer();
  599. $customerData2 = $this->_createCustomer();
  600. $filter1 = $filter1 = $builder->setField(Customer::EMAIL)
  601. ->setValue($customerData1[Customer::EMAIL])
  602. ->create();
  603. $filter2 = $builder->setField(Customer::EMAIL)
  604. ->setValue($customerData2[Customer::EMAIL])
  605. ->create();
  606. $filter3 = $builder->setField(Customer::LASTNAME)
  607. ->setValue('INVALID')
  608. ->create();
  609. $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]);
  610. $this->searchCriteriaBuilder->addFilters([$filter3]);
  611. $searchCriteria = $this->searchCriteriaBuilder->create();
  612. $searchData = $searchCriteria->__toArray();
  613. $requestData = ['searchCriteria' => $searchData];
  614. $serviceInfo = [
  615. 'rest' => [
  616. 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData),
  617. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  618. ],
  619. 'soap' => [
  620. 'service' => self::SERVICE_NAME,
  621. 'serviceVersion' => self::SERVICE_VERSION,
  622. 'operation' => self::SERVICE_NAME . 'getList',
  623. ],
  624. ];
  625. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  626. $this->assertEquals(0, $searchResults['total_count'], 'No results expected for non-existent email.');
  627. }
  628. /**
  629. * Test and verify multiple filters using And-ed non-existent filter value using GET
  630. */
  631. public function testSearchCustomersNonExistentMultipleFiltersGET()
  632. {
  633. $this->_markTestAsRestOnly('SOAP test is covered in testSearchCustomers');
  634. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  635. $customerData1 = $this->_createCustomer();
  636. $customerData2 = $this->_createCustomer();
  637. $filter1 = $filter1 = $builder->setField(Customer::EMAIL)
  638. ->setValue($customerData1[Customer::EMAIL])
  639. ->create();
  640. $filter2 = $builder->setField(Customer::EMAIL)
  641. ->setValue($customerData2[Customer::EMAIL])
  642. ->create();
  643. $filter3 = $builder->setField(Customer::LASTNAME)
  644. ->setValue('INVALID')
  645. ->create();
  646. $this->searchCriteriaBuilder->addFilters([$filter1, $filter2]);
  647. $this->searchCriteriaBuilder->addFilters([$filter3]);
  648. $searchCriteria = $this->searchCriteriaBuilder->create();
  649. $searchData = $searchCriteria->__toArray();
  650. $requestData = ['searchCriteria' => $searchData];
  651. $searchQueryString = http_build_query($requestData);
  652. $serviceInfo = [
  653. 'rest' => [
  654. 'resourcePath' => self::RESOURCE_PATH . '/search?' . $searchQueryString,
  655. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  656. ],
  657. ];
  658. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  659. $this->assertEquals(0, $searchResults['total_count'], 'No results expected for non-existent email.');
  660. }
  661. /**
  662. * Test using multiple filters
  663. */
  664. public function testSearchCustomersMultipleFilterGroups()
  665. {
  666. $customerData1 = $this->_createCustomer();
  667. /** @var \Magento\Framework\Api\FilterBuilder $builder */
  668. $builder = Bootstrap::getObjectManager()->create(\Magento\Framework\Api\FilterBuilder::class);
  669. $filter1 = $builder->setField(Customer::EMAIL)
  670. ->setValue($customerData1[Customer::EMAIL])
  671. ->create();
  672. $filter2 = $builder->setField(Customer::MIDDLENAME)
  673. ->setValue($customerData1[Customer::MIDDLENAME])
  674. ->create();
  675. $filter3 = $builder->setField(Customer::MIDDLENAME)
  676. ->setValue('invalid')
  677. ->create();
  678. $filter4 = $builder->setField(Customer::LASTNAME)
  679. ->setValue($customerData1[Customer::LASTNAME])
  680. ->create();
  681. $this->searchCriteriaBuilder->addFilters([$filter1]);
  682. $this->searchCriteriaBuilder->addFilters([$filter2, $filter3]);
  683. $this->searchCriteriaBuilder->addFilters([$filter4]);
  684. $searchCriteria = $this->searchCriteriaBuilder->setCurrentPage(1)->setPageSize(10)->create();
  685. $searchData = $searchCriteria->__toArray();
  686. $requestData = ['searchCriteria' => $searchData];
  687. $serviceInfo = [
  688. 'rest' => [
  689. 'resourcePath' => self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData),
  690. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  691. ],
  692. 'soap' => [
  693. 'service' => self::SERVICE_NAME,
  694. 'serviceVersion' => self::SERVICE_VERSION,
  695. 'operation' => self::SERVICE_NAME . 'getList',
  696. ],
  697. ];
  698. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  699. $this->assertEquals(1, $searchResults['total_count']);
  700. $this->assertEquals($customerData1[Customer::ID], $searchResults['items'][0][Customer::ID]);
  701. // Add an invalid And-ed data with multiple groups to yield no result
  702. $filter4 = $builder->setField(Customer::LASTNAME)
  703. ->setValue('invalid')
  704. ->create();
  705. $this->searchCriteriaBuilder->addFilters([$filter1]);
  706. $this->searchCriteriaBuilder->addFilters([$filter2, $filter3]);
  707. $this->searchCriteriaBuilder->addFilters([$filter4]);
  708. $searchCriteria = $this->searchCriteriaBuilder->create();
  709. $searchData = $searchCriteria->__toArray();
  710. $requestData = ['searchCriteria' => $searchData];
  711. $serviceInfo['rest']['resourcePath'] = self::RESOURCE_PATH . '/search' . '?' . http_build_query($requestData);
  712. $searchResults = $this->_webApiCall($serviceInfo, $requestData);
  713. $this->assertEquals(0, $searchResults['total_count']);
  714. }
  715. /**
  716. * Retrieve customer data by Id
  717. *
  718. * @param int $customerId
  719. * @return \Magento\Customer\Api\Data\CustomerInterface
  720. */
  721. protected function _getCustomerData($customerId)
  722. {
  723. $customerData = $this->customerRepository->getById($customerId);
  724. $this->customerRegistry->remove($customerId);
  725. return $customerData;
  726. }
  727. /**
  728. * @return array|bool|float|int|string
  729. */
  730. protected function _createCustomer()
  731. {
  732. $customerData = $this->customerHelper->createSampleCustomer();
  733. $this->currentCustomerId[] = $customerData['id'];
  734. return $customerData;
  735. }
  736. }