CartManagementTest.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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\App\Config;
  8. use Magento\TestFramework\TestCase\WebapiAbstract;
  9. /**
  10. * Class CartManagementTest
  11. * @package Magento\Quote\Api
  12. * @magentoAppIsolation enabled
  13. */
  14. class CartManagementTest extends WebapiAbstract
  15. {
  16. const SERVICE_VERSION = 'V1';
  17. const SERVICE_NAME = 'quoteCartManagementV1';
  18. const RESOURCE_PATH = '/V1/carts/';
  19. const RESOURCE_PATH_CUSTOMER_TOKEN = "/V1/integration/customer/token";
  20. protected $createdQuotes = [];
  21. /**
  22. * @var \Magento\TestFramework\ObjectManager
  23. */
  24. protected $objectManager;
  25. protected function setUp()
  26. {
  27. $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  28. $appConfig = $this->objectManager->get(Config::class);
  29. $appConfig->clean();
  30. }
  31. public function tearDown()
  32. {
  33. /** @var \Magento\Quote\Model\Quote $quote */
  34. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class);
  35. foreach ($this->createdQuotes as $quoteId) {
  36. $quote->load($quoteId);
  37. $quote->delete();
  38. }
  39. }
  40. public function testCreateEmptyCartForGuest()
  41. {
  42. $serviceInfo = [
  43. 'rest' => [
  44. 'resourcePath' => self::RESOURCE_PATH,
  45. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  46. ],
  47. 'soap' => [
  48. 'service' => self::SERVICE_NAME,
  49. 'serviceVersion' => self::SERVICE_VERSION,
  50. 'operation' => self::SERVICE_NAME . 'CreateEmptyCart',
  51. ],
  52. ];
  53. $requestData = ['storeId' => 1];
  54. $quoteId = $this->_webApiCall($serviceInfo, $requestData);
  55. $this->assertGreaterThan(0, $quoteId);
  56. $this->createdQuotes[] = $quoteId;
  57. }
  58. /**
  59. * @magentoApiDataFixture Magento/Customer/_files/customer.php
  60. */
  61. public function testCreateEmptyCartForCustomer()
  62. {
  63. /** @var $repository \Magento\Customer\Api\CustomerRepositoryInterface */
  64. $repository = $this->objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class);
  65. /** @var $customer \Magento\Customer\Api\Data\CustomerInterface */
  66. $customer = $repository->getById(1);
  67. $customerId = $customer->getId();
  68. $serviceInfo = [
  69. 'rest' => [
  70. 'resourcePath' => '/V1/customers/' . $customerId . '/carts',
  71. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  72. ],
  73. 'soap' => [
  74. 'service' => self::SERVICE_NAME,
  75. 'serviceVersion' => self::SERVICE_VERSION,
  76. 'operation' => self::SERVICE_NAME . 'CreateEmptyCartForCustomer',
  77. ],
  78. ];
  79. $quoteId = $this->_webApiCall($serviceInfo, ['customerId' => $customerId]);
  80. $this->assertGreaterThan(0, $quoteId);
  81. $this->createdQuotes[] = $quoteId;
  82. }
  83. /**
  84. * @magentoApiDataFixture Magento/Customer/_files/customer.php
  85. */
  86. public function testCreateEmptyCartAndGetCartForCustomer()
  87. {
  88. $this->_markTestAsRestOnly();
  89. // get customer ID token
  90. /** @var \Magento\Integration\Api\CustomerTokenServiceInterface $customerTokenService */
  91. $customerTokenService = $this->objectManager->create(
  92. \Magento\Integration\Api\CustomerTokenServiceInterface::class
  93. );
  94. $token = $customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
  95. $serviceInfo = [
  96. 'rest' => [
  97. 'resourcePath' => '/V1/carts/mine',
  98. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
  99. 'token' => $token
  100. ]
  101. ];
  102. $quoteId = $this->_webApiCall($serviceInfo, ['customerId' => 999]); // customerId 999 will get overridden
  103. $this->assertGreaterThan(0, $quoteId);
  104. $this->createdQuotes[] = $quoteId;
  105. $serviceInfo = [
  106. 'rest' => [
  107. 'resourcePath' => '/V1/carts/mine',
  108. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  109. 'token' => $token
  110. ]
  111. ];
  112. /** @var \Magento\Quote\Api\Data\CartInterface $cart */
  113. $cart = $this->_webApiCall($serviceInfo, ['customerId' => 999]); // customerId 999 will get overridden
  114. $this->assertEquals($quoteId, $cart['id']);
  115. }
  116. /**
  117. * @magentoApiDataFixture Magento/Sales/_files/quote.php
  118. * @magentoApiDataFixture Magento/Customer/_files/customer.php
  119. */
  120. public function testAssignCustomer()
  121. {
  122. /** @var $quote \Magento\Quote\Model\Quote */
  123. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
  124. $cartId = $quote->getId();
  125. /** @var $repository \Magento\Customer\Api\CustomerRepositoryInterface */
  126. $repository = $this->objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class);
  127. /** @var $customer \Magento\Customer\Api\Data\CustomerInterface */
  128. $customer = $repository->getById(1);
  129. $customerId = $customer->getId();
  130. $serviceInfo = [
  131. 'rest' => [
  132. 'resourcePath' => '/V1/carts/' . $cartId,
  133. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  134. ],
  135. 'soap' => [
  136. 'service' => self::SERVICE_NAME,
  137. 'serviceVersion' => 'V1',
  138. 'operation' => self::SERVICE_NAME . 'AssignCustomer',
  139. ],
  140. ];
  141. $requestData = [
  142. 'cartId' => $cartId,
  143. 'customerId' => $customerId,
  144. 'storeId' => 1,
  145. ];
  146. // Cart must be anonymous (see fixture)
  147. $this->assertEmpty($quote->getCustomerId());
  148. $this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
  149. // Reload target quote
  150. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
  151. $this->assertEquals(0, $quote->getCustomerIsGuest());
  152. $this->assertEquals($customer->getId(), $quote->getCustomerId());
  153. $this->assertEquals($customer->getFirstname(), $quote->getCustomerFirstname());
  154. $this->assertEquals($customer->getLastname(), $quote->getCustomerLastname());
  155. }
  156. /**
  157. * @magentoApiDataFixture Magento/Sales/_files/quote.php
  158. * @expectedException \Exception
  159. */
  160. public function testAssignCustomerThrowsExceptionIfThereIsNoCustomerWithGivenId()
  161. {
  162. /** @var $quote \Magento\Quote\Model\Quote */
  163. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
  164. $cartId = $quote->getId();
  165. $customerId = 9999;
  166. $serviceInfo = [
  167. 'soap' => [
  168. 'serviceVersion' => 'V1',
  169. 'service' => self::SERVICE_NAME,
  170. 'operation' => self::SERVICE_NAME . 'AssignCustomer',
  171. ],
  172. 'rest' => [
  173. 'resourcePath' => '/V1/carts/' . $cartId,
  174. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  175. ],
  176. ];
  177. $requestData = [
  178. 'cartId' => $cartId,
  179. 'customerId' => $customerId,
  180. 'storeId' => 1,
  181. ];
  182. $this->_webApiCall($serviceInfo, $requestData);
  183. }
  184. /**
  185. * @magentoApiDataFixture Magento/Customer/_files/customer.php
  186. * @expectedException \Exception
  187. */
  188. public function testAssignCustomerThrowsExceptionIfThereIsNoCartWithGivenId()
  189. {
  190. $cartId = 9999;
  191. $customerId = 1;
  192. $serviceInfo = [
  193. 'soap' => [
  194. 'service' => self::SERVICE_NAME,
  195. 'serviceVersion' => 'V1',
  196. 'operation' => self::SERVICE_NAME . 'AssignCustomer',
  197. ],
  198. 'rest' => [
  199. 'resourcePath' => '/V1/carts/' . $cartId,
  200. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  201. ],
  202. ];
  203. $requestData = [
  204. 'cartId' => $cartId,
  205. 'customerId' => $customerId,
  206. 'storeId' => 1,
  207. ];
  208. $this->_webApiCall($serviceInfo, $requestData);
  209. }
  210. /**
  211. * @magentoApiDataFixture Magento/Sales/_files/quote_with_customer.php
  212. * @expectedException \Exception
  213. * @expectedExceptionMessage The customer can't be assigned to the cart because the cart isn't anonymous.
  214. */
  215. public function testAssignCustomerThrowsExceptionIfTargetCartIsNotAnonymous()
  216. {
  217. /** @var $customer \Magento\Customer\Model\Customer */
  218. $customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class)->load(1);
  219. $customerId = $customer->getId();
  220. /** @var $quote \Magento\Quote\Model\Quote */
  221. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
  222. $cartId = $quote->getId();
  223. $serviceInfo = [
  224. 'rest' => [
  225. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  226. 'resourcePath' => '/V1/carts/' . $cartId,
  227. ],
  228. 'soap' => [
  229. 'service' => self::SERVICE_NAME,
  230. 'serviceVersion' => 'V1',
  231. 'operation' => self::SERVICE_NAME . 'AssignCustomer',
  232. ],
  233. ];
  234. $requestData = [
  235. 'cartId' => $cartId,
  236. 'customerId' => $customerId,
  237. 'storeId' => 1,
  238. ];
  239. $this->_webApiCall($serviceInfo, $requestData);
  240. }
  241. /**
  242. * @magentoApiDataFixture Magento/Sales/_files/quote.php
  243. * @magentoApiDataFixture Magento/Customer/_files/customer_non_default_website_id.php
  244. * @expectedException \Exception
  245. * @expectedExceptionMessage The customer can't be assigned to the cart. The cart belongs to a different store.
  246. */
  247. public function testAssignCustomerThrowsExceptionIfCartIsAssignedToDifferentStore()
  248. {
  249. $repository = $this->objectManager->create(\Magento\Customer\Api\CustomerRepositoryInterface::class);
  250. /** @var $customer \Magento\Customer\Api\Data\CustomerInterface */
  251. $customer = $repository->getById(1);
  252. /** @var $quote \Magento\Quote\Model\Quote */
  253. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
  254. $customerId = $customer->getId();
  255. $cartId = $quote->getId();
  256. $serviceInfo = [
  257. 'soap' => [
  258. 'service' => self::SERVICE_NAME,
  259. 'serviceVersion' => 'V1',
  260. 'operation' => self::SERVICE_NAME . 'AssignCustomer',
  261. ],
  262. 'rest' => [
  263. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  264. 'resourcePath' => '/V1/carts/' . $cartId,
  265. ],
  266. ];
  267. $requestData = [
  268. 'cartId' => $cartId,
  269. 'customerId' => $customerId,
  270. 'storeId' => 1,
  271. ];
  272. $this->_webApiCall($serviceInfo, $requestData);
  273. }
  274. /**
  275. * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
  276. * @magentoApiDataFixture Magento/Sales/_files/quote.php
  277. * @expectedException \Exception
  278. */
  279. public function testAssignCustomerThrowsExceptionIfCustomerAlreadyHasActiveCart()
  280. {
  281. /** @var $customer \Magento\Customer\Model\Customer */
  282. $customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class)->load(1);
  283. // Customer has a quote with reserved order ID test_order_1 (see fixture)
  284. /** @var $customerQuote \Magento\Quote\Model\Quote */
  285. $customerQuote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)
  286. ->load('test_order_1', 'reserved_order_id');
  287. $customerQuote->setIsActive(1)->save();
  288. /** @var $quote \Magento\Quote\Model\Quote */
  289. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load('test01', 'reserved_order_id');
  290. $cartId = $quote->getId();
  291. $customerId = $customer->getId();
  292. $serviceInfo = [
  293. 'soap' => [
  294. 'service' => self::SERVICE_NAME,
  295. 'operation' => self::SERVICE_NAME . 'AssignCustomer',
  296. 'serviceVersion' => 'V1',
  297. ],
  298. 'rest' => [
  299. 'resourcePath' => '/V1/carts/' . $cartId,
  300. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  301. ],
  302. ];
  303. $requestData = [
  304. 'cartId' => $cartId,
  305. 'customerId' => $customerId,
  306. 'storeId' => 1,
  307. ];
  308. $this->_webApiCall($serviceInfo, $requestData);
  309. $this->expectExceptionMessage(
  310. "The customer can't be assigned to the cart because the customer already has an active cart."
  311. );
  312. }
  313. /**
  314. * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php
  315. */
  316. public function testPlaceOrder()
  317. {
  318. /** @var $quote \Magento\Quote\Model\Quote */
  319. $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)
  320. ->load('test_order_1', 'reserved_order_id');
  321. $cartId = $quote->getId();
  322. $serviceInfo = [
  323. 'soap' => [
  324. 'service' => 'quoteCartManagementV1',
  325. 'operation' => 'quoteCartManagementV1PlaceOrder',
  326. 'serviceVersion' => 'V1',
  327. ],
  328. 'rest' => [
  329. 'resourcePath' => '/V1/carts/' . $cartId . '/order',
  330. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  331. ],
  332. ];
  333. $orderId = $this->_webApiCall($serviceInfo, ['cartId' => $cartId]);
  334. /** @var \Magento\Sales\Model\Order $order */
  335. $order = $this->objectManager->create(\Magento\Sales\Model\Order::class)->load($orderId);
  336. $items = $order->getAllItems();
  337. $this->assertCount(1, $items);
  338. $this->assertEquals('Simple Product', $items[0]->getName());
  339. }
  340. /**
  341. * @magentoApiDataFixture Magento/Checkout/_files/quote_with_check_payment.php
  342. */
  343. public function testPlaceOrderForMyCart()
  344. {
  345. $this->_markTestAsRestOnly();
  346. // get customer ID token
  347. /** @var \Magento\Integration\Api\CustomerTokenServiceInterface $customerTokenService */
  348. $customerTokenService = $this->objectManager->create(
  349. \Magento\Integration\Api\CustomerTokenServiceInterface::class
  350. );
  351. $token = $customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
  352. $serviceInfo = [
  353. 'rest' => [
  354. 'resourcePath' => '/V1/carts/mine/order',
  355. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT,
  356. 'token' => $token
  357. ],
  358. ];
  359. $orderId = $this->_webApiCall($serviceInfo, []);
  360. /** @var \Magento\Sales\Model\Order $order */
  361. $order = $this->objectManager->create(\Magento\Sales\Model\Order::class)->load($orderId);
  362. $items = $order->getAllItems();
  363. $this->assertCount(1, $items);
  364. $this->assertEquals('Simple Product', $items[0]->getName());
  365. }
  366. /**
  367. * Test to get my cart based on customer authentication token or session
  368. *
  369. * @magentoApiDataFixture Magento/Sales/_files/quote_with_customer.php
  370. */
  371. public function testGetCartForCustomer()
  372. {
  373. // get customer ID token
  374. /** @var \Magento\Integration\Api\CustomerTokenServiceInterface $customerTokenService */
  375. $customerTokenService = $this->objectManager->create(
  376. \Magento\Integration\Api\CustomerTokenServiceInterface::class
  377. );
  378. $token = $customerTokenService->createCustomerAccessToken('customer@example.com', 'password');
  379. $cart = $this->getCart('test01');
  380. $customerId = $cart->getCustomer()->getId();
  381. $serviceInfo = [
  382. 'rest' => [
  383. 'resourcePath' => '/V1/carts/mine',
  384. 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET,
  385. 'token' => $token
  386. ],
  387. 'soap' => [
  388. 'service' => 'quoteCartManagementV1',
  389. 'serviceVersion' => 'V1',
  390. 'operation' => 'quoteCartManagementV1GetCartForCustomer',
  391. 'token' => $token
  392. ],
  393. ];
  394. $requestData = ['customerId' => $customerId];
  395. $cartData = $this->_webApiCall($serviceInfo, $requestData);
  396. $this->assertEquals($cart->getId(), $cartData['id']);
  397. $this->assertEquals($cart->getCreatedAt(), $cartData['created_at']);
  398. $this->assertEquals($cart->getUpdatedAt(), $cartData['updated_at']);
  399. $this->assertEquals($cart->getIsActive(), $cartData['is_active']);
  400. $this->assertEquals($cart->getIsVirtual(), $cartData['is_virtual']);
  401. $this->assertEquals($cart->getOrigOrderId(), $cartData['orig_order_id']);
  402. $this->assertEquals($cart->getItemsCount(), $cartData['items_count']);
  403. $this->assertEquals($cart->getItemsQty(), $cartData['items_qty']);
  404. $this->assertContains('customer', $cartData);
  405. $this->assertEquals(false, $cartData['customer_is_guest']);
  406. $this->assertContains('currency', $cartData);
  407. $this->assertEquals($cart->getGlobalCurrencyCode(), $cartData['currency']['global_currency_code']);
  408. $this->assertEquals($cart->getBaseCurrencyCode(), $cartData['currency']['base_currency_code']);
  409. $this->assertEquals($cart->getQuoteCurrencyCode(), $cartData['currency']['quote_currency_code']);
  410. $this->assertEquals($cart->getStoreCurrencyCode(), $cartData['currency']['store_currency_code']);
  411. $this->assertEquals($cart->getBaseToGlobalRate(), $cartData['currency']['base_to_global_rate']);
  412. $this->assertEquals($cart->getBaseToQuoteRate(), $cartData['currency']['base_to_quote_rate']);
  413. $this->assertEquals($cart->getStoreToBaseRate(), $cartData['currency']['store_to_base_rate']);
  414. $this->assertEquals($cart->getStoreToQuoteRate(), $cartData['currency']['store_to_quote_rate']);
  415. }
  416. /**
  417. * Retrieve quote by given reserved order ID
  418. *
  419. * @param string $reservedOrderId
  420. * @return \Magento\Quote\Model\Quote
  421. * @throws \InvalidArgumentException
  422. */
  423. protected function getCart($reservedOrderId)
  424. {
  425. /** @var $cart \Magento\Quote\Model\Quote */
  426. $cart = $this->objectManager->get(\Magento\Quote\Model\Quote::class);
  427. $cart->load($reservedOrderId, 'reserved_order_id');
  428. if (!$cart->getId()) {
  429. throw new \InvalidArgumentException('There is no quote with provided reserved order ID.');
  430. }
  431. return $cart;
  432. }
  433. }