AddressRepositoryTest.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Model\ResourceModel;
  7. use Magento\Customer\Api\AddressRepositoryInterface;
  8. use Magento\Customer\Api\CustomerRepositoryInterface;
  9. use Magento\Customer\Api\Data\CustomerInterface;
  10. use Magento\Customer\Api\Data\RegionInterfaceFactory;
  11. use Magento\Framework\Api\SortOrder;
  12. use Magento\Framework\Exception\InputException;
  13. use Magento\Framework\Exception\NoSuchEntityException;
  14. use Magento\Store\Api\Data\WebsiteInterface;
  15. use Magento\Store\Api\WebsiteRepositoryInterface;
  16. /**
  17. * Class with integration tests for AddressRepository.
  18. *
  19. * @SuppressWarnings(PHPMD.TooManyMethods)
  20. * @SuppressWarnings(PHPMD.ExcessivePublicCount)
  21. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  22. */
  23. class AddressRepositoryTest extends \PHPUnit\Framework\TestCase
  24. {
  25. /** @var AddressRepositoryInterface */
  26. private $repository;
  27. /** @var \Magento\Framework\ObjectManagerInterface */
  28. private $objectManager;
  29. /** @var \Magento\Customer\Model\Data\Address[] */
  30. private $expectedAddresses;
  31. /** @var \Magento\Customer\Api\Data\AddressInterfaceFactory */
  32. private $addressFactory;
  33. /** @var \Magento\Framework\Api\DataObjectHelper */
  34. private $dataObjectHelper;
  35. /**
  36. * Set up.
  37. */
  38. protected function setUp()
  39. {
  40. $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  41. /* @var \Magento\Framework\Config\CacheInterface $cache */
  42. $cache = $this->objectManager->create(\Magento\Framework\Config\CacheInterface::class);
  43. $cache->remove('extension_attributes_config');
  44. $this->repository = $this->objectManager->create(\Magento\Customer\Api\AddressRepositoryInterface::class);
  45. $this->addressFactory = $this->objectManager->create(
  46. \Magento\Customer\Api\Data\AddressInterfaceFactory::class
  47. );
  48. $this->dataObjectHelper = $this->objectManager->create(\Magento\Framework\Api\DataObjectHelper::class);
  49. $regionFactory = $this->objectManager->get(RegionInterfaceFactory::class);
  50. $region = $regionFactory->create()
  51. ->setRegionCode('AL')
  52. ->setRegion('Alabama')
  53. ->setRegionId(1);
  54. $address = $this->addressFactory->create()
  55. ->setId('1')
  56. ->setCountryId('US')
  57. ->setCustomerId('1')
  58. ->setPostcode('75477')
  59. ->setRegion($region)
  60. ->setRegionId(1)
  61. ->setStreet(['Green str, 67'])
  62. ->setTelephone('3468676')
  63. ->setCity('CityM')
  64. ->setFirstname('John')
  65. ->setLastname('Smith')
  66. ->setCompany('CompanyName');
  67. $address2 = $this->addressFactory->create()
  68. ->setId('2')
  69. ->setCountryId('US')
  70. ->setCustomerId('1')
  71. ->setPostcode('47676')
  72. ->setRegion($region)
  73. ->setRegionId(1)
  74. ->setStreet(['Black str, 48'])
  75. ->setCity('CityX')
  76. ->setTelephone('3234676')
  77. ->setFirstname('John')
  78. ->setLastname('Smith');
  79. $this->expectedAddresses = [$address, $address2];
  80. }
  81. /**
  82. * Tear down.
  83. */
  84. protected function tearDown()
  85. {
  86. $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  87. /** @var \Magento\Customer\Model\CustomerRegistry $customerRegistry */
  88. $customerRegistry = $objectManager->get(\Magento\Customer\Model\CustomerRegistry::class);
  89. $customerRegistry->remove(1);
  90. }
  91. /**
  92. * Test for save address changes.
  93. *
  94. * @magentoDataFixture Magento/Customer/_files/customer.php
  95. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  96. * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
  97. * @magentoAppIsolation enabled
  98. */
  99. public function testSaveAddressChanges()
  100. {
  101. $address = $this->repository->getById(2);
  102. $proposedAddressObject = $address;
  103. $proposedAddressObject->setRegion($address->getRegion());
  104. // change phone #
  105. $proposedAddressObject->setTelephone('555' . $address->getTelephone());
  106. $proposedAddress = $this->repository->save($proposedAddressObject);
  107. $this->assertEquals(2, $proposedAddress->getId());
  108. $savedAddress = $this->repository->getById(2);
  109. $this->assertNotEquals($this->expectedAddresses[1]->getTelephone(), $savedAddress->getTelephone());
  110. }
  111. /**
  112. * Test for method save address with new id.
  113. *
  114. * @magentoDataFixture Magento/Customer/_files/customer.php
  115. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  116. * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
  117. * @magentoAppIsolation enabled
  118. * @expectedException \Magento\Framework\Exception\NoSuchEntityException
  119. * @expectedExceptionMessage No such entity with addressId = 4200
  120. */
  121. public function testSaveAddressesIdSetButNotAlreadyExisting()
  122. {
  123. $proposedAddress = $this->_createSecondAddress()->setId(4200);
  124. $this->repository->save($proposedAddress);
  125. }
  126. /**
  127. * Test for method get address by id.
  128. *
  129. * @magentoDataFixture Magento/Customer/_files/customer.php
  130. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  131. * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
  132. * @magentoAppIsolation enabled
  133. */
  134. public function testGetAddressById()
  135. {
  136. $addressId = 2;
  137. $address = $this->repository->getById($addressId);
  138. $this->assertEquals($this->expectedAddresses[1], $address);
  139. }
  140. /**
  141. * Test for method get address by id with incorrect id.
  142. *
  143. * @magentoDataFixture Magento/Customer/_files/customer.php
  144. * @expectedException \Magento\Framework\Exception\NoSuchEntityException
  145. * @expectedExceptionMessage No such entity with addressId = 12345
  146. */
  147. public function testGetAddressByIdBadAddressId()
  148. {
  149. $this->repository->getById(12345);
  150. }
  151. /**
  152. * Test for method save new address.
  153. *
  154. * @magentoDataFixture Magento/Customer/_files/customer.php
  155. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  156. * @magentoAppIsolation enabled
  157. */
  158. public function testSaveNewAddress()
  159. {
  160. $proposedAddress = $this->_createSecondAddress()->setCustomerId(1);
  161. $returnedAddress = $this->repository->save($proposedAddress);
  162. $this->assertNotNull($returnedAddress->getId());
  163. $savedAddress = $this->repository->getById($returnedAddress->getId());
  164. $expectedNewAddress = $this->expectedAddresses[1];
  165. $expectedNewAddress->setId($savedAddress->getId());
  166. $expectedNewAddress->setRegion($this->expectedAddresses[1]->getRegion());
  167. $this->assertEquals($expectedNewAddress->getExtensionAttributes(), $savedAddress->getExtensionAttributes());
  168. $this->assertEquals(
  169. $expectedNewAddress->getRegion()->getExtensionAttributes(),
  170. $savedAddress->getRegion()->getExtensionAttributes()
  171. );
  172. $this->assertEquals($expectedNewAddress, $savedAddress);
  173. }
  174. /**
  175. * Test for method saaveNewAddress with new attributes.
  176. *
  177. * @magentoDataFixture Magento/Customer/_files/customer.php
  178. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  179. * @magentoAppIsolation enabled
  180. */
  181. public function testSaveNewAddressWithAttributes()
  182. {
  183. $proposedAddress = $this->_createFirstAddress()
  184. ->setCustomAttribute('firstname', 'Jane')
  185. ->setCustomAttribute('id', 4200)
  186. ->setCustomAttribute('weird', 'something_strange_with_hair')
  187. ->setId(null)
  188. ->setCustomerId(1);
  189. $returnedAddress = $this->repository->save($proposedAddress);
  190. $savedAddress = $this->repository->getById($returnedAddress->getId());
  191. $this->assertNotEquals($proposedAddress, $savedAddress);
  192. $this->assertArrayNotHasKey(
  193. 'weird',
  194. $savedAddress->getCustomAttributes(),
  195. 'Only valid attributes should be available.'
  196. );
  197. }
  198. /**
  199. * Test for saving address with invalid address.
  200. *
  201. * @magentoDataFixture Magento/Customer/_files/customer.php
  202. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  203. * @magentoAppIsolation enabled
  204. */
  205. public function testSaveNewInvalidAddress()
  206. {
  207. $address = $this->_createFirstAddress()
  208. ->setCustomAttribute('firstname', null)
  209. ->setId(null)
  210. ->setFirstname(null)
  211. ->setLastname(null)
  212. ->setCustomerId(1);
  213. try {
  214. $this->repository->save($address);
  215. } catch (InputException $exception) {
  216. $this->assertEquals('One or more input exceptions have occurred.', $exception->getMessage());
  217. $errors = $exception->getErrors();
  218. $this->assertCount(2, $errors);
  219. $this->assertEquals('"firstname" is required. Enter and try again.', $errors[0]->getLogMessage());
  220. $this->assertEquals('"lastname" is required. Enter and try again.', $errors[1]->getLogMessage());
  221. }
  222. }
  223. /**
  224. * Test for saving address without existing customer.
  225. *
  226. * @return void
  227. */
  228. public function testSaveAddressesCustomerIdNotExist()
  229. {
  230. $proposedAddress = $this->_createSecondAddress()->setCustomerId(4200);
  231. try {
  232. $this->repository->save($proposedAddress);
  233. $this->fail('Expected exception not thrown');
  234. } catch (NoSuchEntityException $nsee) {
  235. $this->assertEquals('No such entity with customerId = 4200', $nsee->getMessage());
  236. }
  237. }
  238. /**
  239. * Test for saving addresses with invalid customer id.
  240. *
  241. * @return void
  242. */
  243. public function testSaveAddressesCustomerIdInvalid()
  244. {
  245. $proposedAddress = $this->_createSecondAddress()->setCustomerId('this_is_not_a_valid_id');
  246. try {
  247. $this->repository->save($proposedAddress);
  248. $this->fail('Expected exception not thrown');
  249. } catch (NoSuchEntityException $nsee) {
  250. $this->assertEquals('No such entity with customerId = this_is_not_a_valid_id', $nsee->getMessage());
  251. }
  252. }
  253. /**
  254. * Test for delete method.
  255. *
  256. * @magentoDataFixture Magento/Customer/_files/customer.php
  257. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  258. */
  259. public function testDeleteAddress()
  260. {
  261. $addressId = 1;
  262. // See that customer already has an address with expected addressId
  263. $addressDataObject = $this->repository->getById($addressId);
  264. $this->assertEquals($addressDataObject->getId(), $addressId);
  265. // Delete the address from the customer
  266. $this->repository->delete($addressDataObject);
  267. // See that address is deleted
  268. try {
  269. $addressDataObject = $this->repository->getById($addressId);
  270. $this->fail("Expected NoSuchEntityException not caught");
  271. } catch (NoSuchEntityException $exception) {
  272. $this->assertEquals('No such entity with addressId = 1', $exception->getMessage());
  273. }
  274. }
  275. /**
  276. * Test for deleteAddressById.
  277. *
  278. * @magentoDataFixture Magento/Customer/_files/customer.php
  279. * @magentoDataFixture Magento/Customer/_files/customer_address.php
  280. */
  281. public function testDeleteAddressById()
  282. {
  283. $addressId = 1;
  284. // See that customer already has an address with expected addressId
  285. $addressDataObject = $this->repository->getById($addressId);
  286. $this->assertEquals($addressDataObject->getId(), $addressId);
  287. // Delete the address from the customer
  288. $this->repository->deleteById($addressId);
  289. // See that address is deleted
  290. try {
  291. $addressDataObject = $this->repository->getById($addressId);
  292. $this->fail("Expected NoSuchEntityException not caught");
  293. } catch (NoSuchEntityException $exception) {
  294. $this->assertEquals('No such entity with addressId = 1', $exception->getMessage());
  295. }
  296. }
  297. /**
  298. * Test delete address from customer with incorrect address id.
  299. *
  300. * @magentoDataFixture Magento/Customer/_files/customer.php
  301. */
  302. public function testDeleteAddressFromCustomerBadAddressId()
  303. {
  304. try {
  305. $this->repository->deleteById(12345);
  306. $this->fail("Expected NoSuchEntityException not caught");
  307. } catch (NoSuchEntityException $exception) {
  308. $this->assertEquals('No such entity with addressId = 12345', $exception->getMessage());
  309. }
  310. }
  311. /**
  312. * Test for searching addressed.
  313. *
  314. * @param \Magento\Framework\Api\Filter[] $filters
  315. * @param \Magento\Framework\Api\Filter[] $filterGroup
  316. * @param \Magento\Framework\Api\SortOrder[] $filterOrders
  317. * @param array $expectedResult array of expected results indexed by ID
  318. * @param int $currentPage current page for search criteria
  319. *
  320. * @dataProvider searchAddressDataProvider
  321. *
  322. * @magentoDataFixture Magento/Customer/_files/customer.php
  323. * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php
  324. * @magentoAppIsolation enabled
  325. */
  326. public function testSearchAddresses($filters, $filterGroup, $filterOrders, $expectedResult, $currentPage)
  327. {
  328. /** @var \Magento\Framework\Api\SearchCriteriaBuilder $searchBuilder */
  329. $searchBuilder = $this->objectManager->create(\Magento\Framework\Api\SearchCriteriaBuilder::class);
  330. foreach ($filters as $filter) {
  331. $searchBuilder->addFilters([$filter]);
  332. }
  333. if ($filterGroup !== null) {
  334. $searchBuilder->addFilters($filterGroup);
  335. }
  336. if ($filterOrders !== null) {
  337. foreach ($filterOrders as $order) {
  338. $searchBuilder->addSortOrder($order);
  339. }
  340. }
  341. $searchBuilder->setPageSize(1);
  342. $searchBuilder->setCurrentPage($currentPage);
  343. $searchCriteria = $searchBuilder->create();
  344. $searchResults = $this->repository->getList($searchCriteria);
  345. $items = array_values($searchResults->getItems());
  346. $this->assertEquals(count($expectedResult), $searchResults->getTotalCount());
  347. $this->assertEquals(1, count($items));
  348. $expectedResultIndex = count($expectedResult) - 1;
  349. $this->assertEquals($expectedResult[$expectedResultIndex]['id'], $items[0]->getId());
  350. $this->assertEquals($expectedResult[$expectedResultIndex]['city'], $items[0]->getCity());
  351. $this->assertEquals($expectedResult[$expectedResultIndex]['postcode'], $items[0]->getPostcode());
  352. $this->assertEquals($expectedResult[$expectedResultIndex]['firstname'], $items[0]->getFirstname());
  353. }
  354. /**
  355. * Data provider for searchAddresses.
  356. *
  357. * @return array
  358. */
  359. public function searchAddressDataProvider()
  360. {
  361. /**
  362. * @var \Magento\Framework\Api\FilterBuilder $filterBuilder
  363. */
  364. $filterBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
  365. ->create(\Magento\Framework\Api\FilterBuilder::class);
  366. /**
  367. * @var \Magento\Framework\Api\SortOrderBuilder $orderBuilder
  368. */
  369. $orderBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
  370. ->create(\Magento\Framework\Api\SortOrderBuilder::class);
  371. return [
  372. 'Address with postcode 75477' => [
  373. [$filterBuilder->setField('postcode')->setValue('75477')->create()],
  374. null,
  375. null,
  376. [
  377. ['id' => 1, 'city' => 'CityM', 'postcode' => 75477, 'firstname' => 'John'],
  378. ],
  379. 1
  380. ],
  381. 'Address with city CityM' => [
  382. [$filterBuilder->setField('city')->setValue('CityM')->create()],
  383. null,
  384. null,
  385. [
  386. ['id' => 1, 'city' => 'CityM', 'postcode' => 75477, 'firstname' => 'John'],
  387. ],
  388. 1
  389. ],
  390. 'Addresses with firstname John sorted by firstname desc, city asc' => [
  391. [$filterBuilder->setField('firstname')->setValue('John')->create()],
  392. null,
  393. [
  394. $orderBuilder->setField('firstname')->setDirection(SortOrder::SORT_DESC)->create(),
  395. $orderBuilder->setField('city')->setDirection(SortOrder::SORT_ASC)->create(),
  396. ],
  397. [
  398. ['id' => 1, 'city' => 'CityM', 'postcode' => 75477, 'firstname' => 'John'],
  399. ['id' => 2, 'city' => 'CityX', 'postcode' => 47676, 'firstname' => 'John'],
  400. ],
  401. 2
  402. ],
  403. 'Addresses with postcode of either 75477 or 47676 sorted by city desc' => [
  404. [],
  405. [
  406. $filterBuilder->setField('postcode')->setValue('75477')->create(),
  407. $filterBuilder->setField('postcode')->setValue('47676')->create(),
  408. ],
  409. [
  410. $orderBuilder->setField('city')->setDirection(SortOrder::SORT_DESC)->create(),
  411. ],
  412. [
  413. ['id' => 2, 'city' => 'CityX', 'postcode' => 47676, 'firstname' => 'John'],
  414. ['id' => 1, 'city' => 'CityM', 'postcode' => 75477, 'firstname' => 'John'],
  415. ],
  416. 2
  417. ],
  418. 'Addresses with postcode greater than 0 sorted by firstname asc, postcode desc' => [
  419. [$filterBuilder->setField('postcode')->setValue('0')->setConditionType('gt')->create()],
  420. null,
  421. [
  422. $orderBuilder->setField('firstname')->setDirection(SortOrder::SORT_ASC)->create(),
  423. $orderBuilder->setField('postcode')->setDirection(SortOrder::SORT_ASC)->create(),
  424. ],
  425. [
  426. ['id' => 2, 'city' => 'CityX', 'postcode' => 47676, 'firstname' => 'John'],
  427. ['id' => 1, 'city' => 'CityM', 'postcode' => 75477, 'firstname' => 'John'],
  428. ],
  429. 2
  430. ],
  431. ];
  432. }
  433. /**
  434. * Test for save addresses with restricted countries.
  435. *
  436. * @magentoDataFixture Magento/Customer/Fixtures/customer_sec_website.php
  437. */
  438. public function testSaveAddressWithRestrictedCountries()
  439. {
  440. $website = $this->getWebsite('test');
  441. $customer = $this->getCustomer('customer.web@example.com', (int)$website->getId());
  442. $regionFactory = $this->objectManager->get(RegionInterfaceFactory::class);
  443. $region = $regionFactory->create()
  444. ->setRegionCode('CA')
  445. ->setRegion('California')
  446. ->setRegionId(12);
  447. $addressData = [
  448. 'customer_id' => $customer->getId(),
  449. 'firstname' => 'John',
  450. 'lastname' => 'Doe',
  451. 'street' => ['6161 Main Street'],
  452. 'city' => 'Culver City',
  453. 'country_id' => 'US',
  454. 'region' => $region,
  455. 'postcode' => 90230,
  456. 'telephone' => '555655431'
  457. ];
  458. $address = $this->addressFactory->create(['data' => $addressData]);
  459. $saved = $this->repository->save($address);
  460. self::assertNotEmpty($saved->getId());
  461. }
  462. /**
  463. * Helper function that returns an Address Data Object that matches the data from customer_address fixture
  464. *
  465. * @return \Magento\Customer\Api\Data\AddressInterface
  466. */
  467. private function _createFirstAddress()
  468. {
  469. $address = $this->addressFactory->create();
  470. $this->dataObjectHelper->mergeDataObjects(
  471. \Magento\Customer\Api\Data\AddressInterface::class,
  472. $address,
  473. $this->expectedAddresses[0]
  474. );
  475. $address->setId(null);
  476. $address->setRegion($this->expectedAddresses[0]->getRegion());
  477. return $address;
  478. }
  479. /**
  480. * Helper function that returns an Address Data Object that matches the data from customer_two_address fixture
  481. *
  482. * @return \Magento\Customer\Api\Data\AddressInterface
  483. */
  484. private function _createSecondAddress()
  485. {
  486. $address = $this->addressFactory->create();
  487. $this->dataObjectHelper->mergeDataObjects(
  488. \Magento\Customer\Api\Data\AddressInterface::class,
  489. $address,
  490. $this->expectedAddresses[1]
  491. );
  492. $address->setId(null);
  493. $address->setRegion($this->expectedAddresses[1]->getRegion());
  494. return $address;
  495. }
  496. /**
  497. * Gets customer entity.
  498. *
  499. * @param string $email
  500. * @param int $websiteId
  501. * @return CustomerInterface
  502. * @throws NoSuchEntityException
  503. * @throws \Magento\Framework\Exception\LocalizedException
  504. */
  505. private function getCustomer(string $email, int $websiteId): CustomerInterface
  506. {
  507. /** @var CustomerRepositoryInterface $repository */
  508. $repository = $this->objectManager->get(CustomerRepositoryInterface::class);
  509. return $repository->get($email, $websiteId);
  510. }
  511. /**
  512. * Gets website entity.
  513. *
  514. * @param string $code
  515. * @return WebsiteInterface
  516. * @throws NoSuchEntityException
  517. */
  518. private function getWebsite(string $code): WebsiteInterface
  519. {
  520. /** @var WebsiteRepositoryInterface $repository */
  521. $repository = $this->objectManager->get(WebsiteRepositoryInterface::class);
  522. return $repository->get($code);
  523. }
  524. }