CartRepositoryTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Quote\Api;
  7. use Magento\Framework\Api\FilterBuilder;
  8. use Magento\Framework\Api\SearchCriteriaBuilder;
  9. use Magento\Framework\Api\SortOrderBuilder;
  10. use Magento\Framework\Api\SortOrder;
  11. use Magento\TestFramework\ObjectManager;
  12. use Magento\TestFramework\TestCase\WebapiAbstract;
  13. use Magento\Quote\Model\Quote;
  14. use Magento\Integration\Api\CustomerTokenServiceInterface;
  15. use Magento\Framework\Webapi\Rest\Request;
  16. /**
  17. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  18. */
  19. class CartRepositoryTest extends WebapiAbstract
  20. {
  21. private static $mineCartUrl = '/V1/carts/mine';
  22. /**
  23. * @var ObjectManager
  24. */
  25. private $objectManager;
  26. /**
  27. * @var SearchCriteriaBuilder
  28. */
  29. private $searchCriteriaBuilder;
  30. /**
  31. * @var SortOrderBuilder
  32. */
  33. private $sortOrderBuilder;
  34. /**
  35. * @var FilterBuilder
  36. */
  37. private $filterBuilder;
  38. protected function setUp()
  39. {
  40. $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  41. $this->filterBuilder = $this->objectManager->create(
  42. \Magento\Framework\Api\FilterBuilder::class
  43. );
  44. $this->sortOrderBuilder = $this->objectManager->create(
  45. \Magento\Framework\Api\SortOrderBuilder::class
  46. );
  47. $this->searchCriteriaBuilder = $this->objectManager->create(
  48. \Magento\Framework\Api\SearchCriteriaBuilder::class
  49. );
  50. }
  51. protected function tearDown()
  52. {
  53. try {
  54. $cart = $this->getCart('test01');
  55. $cart->delete();
  56. } catch (\InvalidArgumentException $e) {
  57. // Do nothing if cart fixture was not used
  58. }
  59. parent::tearDown();
  60. }
  61. /**
  62. * Retrieve quote by given reserved order ID
  63. *
  64. * @param string $reservedOrderId
  65. * @return \Magento\Quote\Model\Quote
  66. * @throws \InvalidArgumentException
  67. */
  68. protected function getCart($reservedOrderId)
  69. {
  70. /** @var $cart \Magento\Quote\Model\Quote */
  71. $cart = $this->objectManager->get(\Magento\Quote\Model\Quote::class);
  72. $cart->load($reservedOrderId, 'reserved_order_id');
  73. if (!$cart->getId()) {
  74. throw new \InvalidArgumentException('There is no quote with provided reserved order ID.');
  75. }
  76. return $cart;
  77. }
  78. /**
  79. * @magentoApiDataFixture Magento/Sales/_files/quote.php
  80. */
  81. public function testGetCart()
  82. {
  83. $cart = $this->getCart('test01');
  84. $cartId = $cart->getId();
  85. $serviceInfo = [
  86. 'rest' => [
  87. 'resourcePath' => '/V1/carts/' . $cartId,
  88. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  89. ],
  90. 'soap' => [
  91. 'service' => 'quoteCartRepositoryV1',
  92. 'serviceVersion' => 'V1',
  93. 'operation' => 'quoteCartRepositoryV1Get',
  94. ],
  95. ];
  96. $requestData = ['cartId' => $cartId];
  97. $cartData = $this->_webApiCall($serviceInfo, $requestData);
  98. $this->assertEquals($cart->getId(), $cartData['id']);
  99. $this->assertEquals($cart->getCreatedAt(), $cartData['created_at']);
  100. $this->assertEquals($cart->getUpdatedAt(), $cartData['updated_at']);
  101. $this->assertEquals($cart->getIsActive(), $cartData['is_active']);
  102. $this->assertEquals($cart->getIsVirtual(), $cartData['is_virtual']);
  103. $this->assertEquals($cart->getOrigOrderId(), $cartData['orig_order_id']);
  104. $this->assertEquals($cart->getItemsCount(), $cartData['items_count']);
  105. $this->assertEquals($cart->getItemsQty(), $cartData['items_qty']);
  106. //following checks will be uncommented when all cart related services are ready
  107. $this->assertContains('customer', $cartData);
  108. $this->assertEquals(true, $cartData['customer_is_guest']);
  109. $this->assertContains('currency', $cartData);
  110. $this->assertEquals($cart->getGlobalCurrencyCode(), $cartData['currency']['global_currency_code']);
  111. $this->assertEquals($cart->getBaseCurrencyCode(), $cartData['currency']['base_currency_code']);
  112. $this->assertEquals($cart->getQuoteCurrencyCode(), $cartData['currency']['quote_currency_code']);
  113. $this->assertEquals($cart->getStoreCurrencyCode(), $cartData['currency']['store_currency_code']);
  114. $this->assertEquals($cart->getBaseToGlobalRate(), $cartData['currency']['base_to_global_rate']);
  115. $this->assertEquals($cart->getBaseToQuoteRate(), $cartData['currency']['base_to_quote_rate']);
  116. $this->assertEquals($cart->getStoreToBaseRate(), $cartData['currency']['store_to_base_rate']);
  117. $this->assertEquals($cart->getStoreToQuoteRate(), $cartData['currency']['store_to_quote_rate']);
  118. }
  119. /**
  120. * @expectedException \Exception
  121. * @expectedExceptionMessage No such entity with
  122. */
  123. public function testGetCartThrowsExceptionIfThereIsNoCartWithProvidedId()
  124. {
  125. $cartId = 9999;
  126. $serviceInfo = [
  127. 'soap' => [
  128. 'service' => 'quoteCartRepositoryV1',
  129. 'serviceVersion' => 'V1',
  130. 'operation' => 'quoteCartRepositoryV1Get',
  131. ],
  132. 'rest' => [
  133. 'resourcePath' => '/V1/carts/' . $cartId,
  134. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  135. ],
  136. ];
  137. $requestData = ['cartId' => $cartId];
  138. $this->_webApiCall($serviceInfo, $requestData);
  139. }
  140. /**
  141. * @magentoApiDataFixture Magento/Sales/_files/quote.php
  142. */
  143. public function testGetList()
  144. {
  145. $cart = $this->getCart('test01');
  146. // The following two filters are used as alternatives. The target cart does not match the first one.
  147. $grandTotalFilter = $this->filterBuilder->setField('grand_total')
  148. ->setConditionType('gteq')
  149. ->setValue(15)
  150. ->create();
  151. $subtotalFilter = $this->filterBuilder->setField('subtotal')
  152. ->setConditionType('eq')
  153. ->setValue($cart->getSubtotal())
  154. ->create();
  155. $yesterdayDate = (new \DateTime($cart->getCreatedAt()))->sub(new \DateInterval('P1D'))->format('Y-m-d');
  156. $tomorrowDate = (new \DateTime($cart->getCreatedAt()))->add(new \DateInterval('P1D'))->format('Y-m-d');
  157. $minCreatedAtFilter = $this->filterBuilder->setField('created_at')
  158. ->setConditionType('gteq')
  159. ->setValue($yesterdayDate)
  160. ->create();
  161. $maxCreatedAtFilter = $this->filterBuilder->setField('created_at')
  162. ->setConditionType('lteq')
  163. ->setValue($tomorrowDate)
  164. ->create();
  165. $this->searchCriteriaBuilder->addFilters([$grandTotalFilter, $subtotalFilter]);
  166. $this->searchCriteriaBuilder->addFilters([$minCreatedAtFilter]);
  167. $this->searchCriteriaBuilder->addFilters([$maxCreatedAtFilter]);
  168. /** @var SortOrder $sortOrder */
  169. $sortOrder = $this->sortOrderBuilder->setField('subtotal')->setDirection(SortOrder::SORT_ASC)->create();
  170. $this->searchCriteriaBuilder->setSortOrders([$sortOrder]);
  171. $searchCriteria = $this->searchCriteriaBuilder->create()->__toArray();
  172. $requestData = ['searchCriteria' => $searchCriteria];
  173. $serviceInfo = [
  174. 'rest' => [
  175. 'resourcePath' => '/V1/carts/search' . '?' . http_build_query($requestData),
  176. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  177. ],
  178. 'soap' => [
  179. 'service' => 'quoteCartRepositoryV1',
  180. 'serviceVersion' => 'V1',
  181. 'operation' => 'quoteCartRepositoryV1GetList',
  182. ],
  183. ];
  184. $searchResult = $this->_webApiCall($serviceInfo, $requestData);
  185. $this->assertArrayHasKey('total_count', $searchResult);
  186. $this->assertEquals(1, $searchResult['total_count']);
  187. $this->assertArrayHasKey('items', $searchResult);
  188. $this->assertCount(1, $searchResult['items']);
  189. $cartData = $searchResult['items'][0];
  190. $this->assertEquals($cart->getId(), $cartData['id']);
  191. $this->assertEquals($cart->getCreatedAt(), $cartData['created_at']);
  192. $this->assertEquals($cart->getUpdatedAt(), $cartData['updated_at']);
  193. $this->assertEquals($cart->getIsActive(), $cartData['is_active']);
  194. $this->assertContains('customer_is_guest', $cartData);
  195. $this->assertEquals(1, $cartData['customer_is_guest']);
  196. }
  197. /**
  198. * @expectedException \Exception
  199. */
  200. public function testGetListThrowsExceptionIfProvidedSearchFieldIsInvalid()
  201. {
  202. $serviceInfo = [
  203. 'soap' => [
  204. 'service' => 'quoteCartRepositoryV1',
  205. 'serviceVersion' => 'V1',
  206. 'operation' => 'quoteCartRepositoryV1GetList',
  207. ],
  208. 'rest' => [
  209. 'resourcePath' => '/V1/carts/search',
  210. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  211. ],
  212. ];
  213. $invalidFilter = $this->filterBuilder->setField('invalid_field')
  214. ->setConditionType('eq')
  215. ->setValue(0)
  216. ->create();
  217. $this->searchCriteriaBuilder->addFilters([$invalidFilter]);
  218. $searchCriteria = $this->searchCriteriaBuilder->create()->__toArray();
  219. $requestData = ['searchCriteria' => $searchCriteria];
  220. $this->_webApiCall($serviceInfo, $requestData);
  221. }
  222. /**
  223. * Saving quote - negative case, attempt to change customer id in the active quote for the user with Customer role.
  224. *
  225. * @expectedException \Exception
  226. * @expectedExceptionMessage Invalid state change requested
  227. * @dataProvider customerIdDataProvider
  228. * @magentoApiDataFixture Magento/Checkout/_files/quote_with_shipping_method.php
  229. */
  230. public function testSaveQuoteException($customerId)
  231. {
  232. $token = $this->getToken();
  233. /** @var Quote $quote */
  234. $quote = $this->getCart('test_order_1');
  235. $requestData = $this->getRequestData($quote->getId());
  236. // Replace to customer id not much with current user id..
  237. $requestData['quote']['customer']['id'] = $customerId;
  238. $serviceInfo = [
  239. 'rest' => [
  240. 'resourcePath' => self::$mineCartUrl,
  241. 'httpMethod' => Request::HTTP_METHOD_PUT,
  242. 'token' => $token
  243. ],
  244. 'soap' => [
  245. 'service' => 'quoteCartRepositoryV1',
  246. 'serviceVersion' => 'V1',
  247. 'operation' => 'quoteCartRepositoryV1Save',
  248. 'token' => $token
  249. ]
  250. ];
  251. $this->_webApiCall($serviceInfo, $requestData);
  252. }
  253. /**
  254. * Saving quote - positive case: successful change correct customer data.
  255. *
  256. * @magentoApiDataFixture Magento/Checkout/_files/quote_with_shipping_method.php
  257. */
  258. public function testSaveQuote()
  259. {
  260. $token = $this->getToken();
  261. /** @var Quote $quote */
  262. $quote = $this->getCart('test_order_1');
  263. $requestData = $this->getRequestData($quote->getId());
  264. $serviceInfo = [
  265. 'rest' => [
  266. 'resourcePath' => self::$mineCartUrl,
  267. 'httpMethod' => Request::HTTP_METHOD_PUT,
  268. 'token' => $token
  269. ],
  270. 'soap' => [
  271. 'service' => 'quoteCartRepositoryV1',
  272. 'serviceVersion' => 'V1',
  273. 'operation' => 'quoteCartRepositoryV1Save',
  274. 'token' => $token
  275. ]
  276. ];
  277. $this->_webApiCall($serviceInfo, $requestData);
  278. $quote->loadActive($requestData["quote"]["id"]);
  279. $this->assertEquals($requestData["quote"]["customer"]["firstname"], $quote->getCustomerFirstname());
  280. $this->assertEquals($requestData["quote"]["customer"]["middlename"], $quote->getCustomerMiddlename());
  281. $this->assertEquals($requestData["quote"]["customer"]["lastname"], $quote->getCustomerLastname());
  282. $this->assertEquals($requestData["quote"]["customer"]["email"], $quote->getCustomerEmail());
  283. }
  284. /**
  285. * Request to api for the current user token.
  286. *
  287. * @return string
  288. */
  289. private function getToken()
  290. {
  291. $customerTokenService = $this->objectManager->create(
  292. CustomerTokenServiceInterface::class
  293. );
  294. return $customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
  295. }
  296. /**
  297. * Request's data for tests.
  298. *
  299. * @param $quoteId Int
  300. * @return array
  301. */
  302. private function getRequestData($quoteId)
  303. {
  304. $requestData['quote'] = [
  305. 'id' => $quoteId,
  306. 'store_id' => 1,
  307. 'customer' => [
  308. 'id' => 1,
  309. 'middlename' => 'Middlename_Test',
  310. 'firstname' => 'Firstname_Test',
  311. 'lastname' => 'Lastname_Test',
  312. 'email' => 'customer@test.com'
  313. ]
  314. ];
  315. return $requestData;
  316. }
  317. /**
  318. * Provides different types of customer id.
  319. *
  320. * @return array
  321. */
  322. public function customerIdDataProvider()
  323. {
  324. return [[999],[null],['25']];
  325. }
  326. }