From 85d0dd60c9a76b9a37c92ce1021f453324e74b03 Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Fri, 22 Jan 2021 17:08:11 +0200 Subject: [PATCH 1/6] MC-34298: Introduce separate POST and PUT API for carts/mine/items --- .../Quote/Api/AddCartItemInterface.php | 31 ++++++++++++++ .../Quote/Api/CartItemRepositoryInterface.php | 5 +++ .../Quote/Api/UpdateCartItemInterface.php | 31 ++++++++++++++ .../Quote/Model/Quote/Item/AddCartItem.php | 42 +++++++++++++++++++ .../Quote/Model/Quote/Item/UpdateCartItem.php | 38 +++++++++++++++++ app/code/Magento/Quote/etc/webapi.xml | 8 ++-- 6 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 app/code/Magento/Quote/Api/AddCartItemInterface.php create mode 100644 app/code/Magento/Quote/Api/UpdateCartItemInterface.php create mode 100644 app/code/Magento/Quote/Model/Quote/Item/AddCartItem.php create mode 100644 app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php diff --git a/app/code/Magento/Quote/Api/AddCartItemInterface.php b/app/code/Magento/Quote/Api/AddCartItemInterface.php new file mode 100644 index 0000000000000..7e665926366c6 --- /dev/null +++ b/app/code/Magento/Quote/Api/AddCartItemInterface.php @@ -0,0 +1,31 @@ +quoteItemRepository = $quoteItemRepository; + } + + /** + * @inheritDoc + */ + public function execute(CartItemInterface $cartItem) + { + if (isset($cartItem[CartItemInterface::KEY_ITEM_ID])) { + unset($cartItem[CartItemInterface::KEY_ITEM_ID]); + } + + return $this->quoteItemRepository->save($cartItem); + } +} diff --git a/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php b/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php new file mode 100644 index 0000000000000..956affd80bd70 --- /dev/null +++ b/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php @@ -0,0 +1,38 @@ +quoteItemRepository = $quoteItemRepository; + } + + /** + * @inheritDoc + */ + public function execute(CartItemInterface $cartItem) + { + return $this->quoteItemRepository->save($cartItem); + } +} diff --git a/app/code/Magento/Quote/etc/webapi.xml b/app/code/Magento/Quote/etc/webapi.xml index 686bdce07de5f..df1b0fd6e9a00 100644 --- a/app/code/Magento/Quote/etc/webapi.xml +++ b/app/code/Magento/Quote/etc/webapi.xml @@ -177,13 +177,13 @@ - + - + @@ -232,7 +232,7 @@ - + @@ -241,7 +241,7 @@ - + From e026cfb9b3b46840df116230a778a7f07d044b7d Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Fri, 22 Jan 2021 23:17:27 +0200 Subject: [PATCH 2/6] MC-34298: Introduce separate POST and PUT API for carts/mine/items --- .../Magento/Quote/Api/AddCartItemInterface.php | 17 ++++++----------- .../Quote/Api/UpdateCartItemInterface.php | 17 ++++++----------- .../Quote/Model/Quote/Item/UpdateCartItem.php | 4 ++-- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Quote/Api/AddCartItemInterface.php b/app/code/Magento/Quote/Api/AddCartItemInterface.php index 7e665926366c6..bbc94aac68ded 100644 --- a/app/code/Magento/Quote/Api/AddCartItemInterface.php +++ b/app/code/Magento/Quote/Api/AddCartItemInterface.php @@ -7,11 +7,6 @@ namespace Magento\Quote\Api; -use Magento\Framework\Exception\CouldNotSaveException; -use Magento\Framework\Exception\InputException; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Quote\Api\Data\CartItemInterface; - /** * Interface AddCartItemInterface * @api @@ -21,11 +16,11 @@ interface AddCartItemInterface /** * Add the specified cart item. * - * @param CartItemInterface $cartItem The item. - * @return CartItemInterface - * @throws NoSuchEntityException The specified cart does not exist. - * @throws CouldNotSaveException The specified item could not be saved to the cart. - * @throws InputException The specified item or cart is not valid. + * @param \Magento\Quote\Api\Data\CartItemInterface $cartItem The item. + * @return \Magento\Quote\Api\Data\CartItemInterface Item. + * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist. + * @throws \Magento\Framework\Exception\CouldNotSaveException The specified item could not be saved to the cart. + * @throws \Magento\Framework\Exception\InputException The specified item or cart is not valid. */ - public function execute(CartItemInterface $cartItem); + public function execute(\Magento\Quote\Api\Data\CartItemInterface $cartItem); } diff --git a/app/code/Magento/Quote/Api/UpdateCartItemInterface.php b/app/code/Magento/Quote/Api/UpdateCartItemInterface.php index 2244692a984c5..5252297c23c81 100644 --- a/app/code/Magento/Quote/Api/UpdateCartItemInterface.php +++ b/app/code/Magento/Quote/Api/UpdateCartItemInterface.php @@ -7,11 +7,6 @@ namespace Magento\Quote\Api; -use Magento\Framework\Exception\CouldNotSaveException; -use Magento\Framework\Exception\InputException; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Quote\Api\Data\CartItemInterface; - /** * Interface AddCartItemInterface * @api @@ -21,11 +16,11 @@ interface UpdateCartItemInterface /** * Update the specified cart item. * - * @param CartItemInterface $cartItem The item. - * @return CartItemInterface Item. - * @throws NoSuchEntityException The specified cart does not exist. - * @throws CouldNotSaveException The specified item could not be saved to the cart. - * @throws InputException The specified item or cart is not valid. + * @param \Magento\Quote\Api\Data\CartItemInterface $cartItem The item. + * @return \Magento\Quote\Api\Data\CartItemInterface Item. + * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist. + * @throws \Magento\Framework\Exception\CouldNotSaveException The specified item could not be saved to the cart. + * @throws \Magento\Framework\Exception\InputException The specified item or cart is not valid. */ - public function execute(CartItemInterface $cartItem); + public function execute(\Magento\Quote\Api\Data\CartItemInterface $cartItem); } diff --git a/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php b/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php index 956affd80bd70..fac1a0113477c 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php +++ b/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php @@ -7,13 +7,13 @@ namespace Magento\Quote\Model\Quote\Item; -use Magento\Quote\Api\AddCartItemInterface; use Magento\Quote\Api\Data\CartItemInterface; +use Magento\Quote\Api\UpdateCartItemInterface; /** * Update the specified cart item */ -class UpdateCartItem implements AddCartItemInterface +class UpdateCartItem implements UpdateCartItemInterface { /** * @var Repository From b1081e78cffbebcb23fad533674bd646ba1f07d9 Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Sat, 23 Jan 2021 10:11:29 +0200 Subject: [PATCH 3/6] MC-34298: Introduce separate POST and PUT API for carts/mine/items --- app/code/Magento/Quote/etc/di.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml index f66001e7789cf..0b53360b082f8 100644 --- a/app/code/Magento/Quote/etc/di.xml +++ b/app/code/Magento/Quote/etc/di.xml @@ -16,6 +16,8 @@ + + From a4f09a1b9b5ad6c10760d8e8ad89dd4112b2d919 Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Mon, 25 Jan 2021 17:05:29 +0200 Subject: [PATCH 4/6] MC-34298: Introduce separate POST and PUT API for carts/mine/items --- .../Quote/Api/AddCartItemInterface.php | 8 +- .../Quote/Api/UpdateCartItemInterface.php | 8 +- .../Quote/Model/Quote/Item/AddCartItem.php | 2 +- .../Quote/Model/Quote/Item/UpdateCartItem.php | 2 +- .../Magento/Bundle/Api/CartItemAddTest.php | 103 ++++++ .../Bundle/Api/CartItemRepositoryTest.php | 166 +--------- .../Magento/Bundle/Api/CartItemUpdateTest.php | 116 +++++++ .../Magento/Catalog/Api/CartItemAddTest.php | 158 +++++++++ .../Catalog/Api/CartItemRepositoryTest.php | 137 +------- .../Api/CartItemAddTest.php | 159 +++++++++ .../Api/CartItemRepositoryTest.php | 313 +----------------- .../Api/CartItemUpdateTest.php | 257 ++++++++++++++ .../Downloadable/Api/CartItemAddTest.php | 139 ++++++++ .../Api/CartItemRepositoryTest.php | 276 +-------------- .../Downloadable/Api/CartItemUpdateTest.php | 191 +++++++++++ .../Magento/Quote/Api/CartItemAddTest.php | 76 +++++ .../Quote/Api/CartItemRepositoryTest.php | 107 +----- .../Magento/Quote/Api/CartItemUpdateTest.php | 89 +++++ 18 files changed, 1377 insertions(+), 930 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemUpdateTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemAddTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemAddTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemUpdateTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemAddTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemUpdateTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemAddTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemUpdateTest.php diff --git a/app/code/Magento/Quote/Api/AddCartItemInterface.php b/app/code/Magento/Quote/Api/AddCartItemInterface.php index bbc94aac68ded..dc50cd1e882ae 100644 --- a/app/code/Magento/Quote/Api/AddCartItemInterface.php +++ b/app/code/Magento/Quote/Api/AddCartItemInterface.php @@ -7,6 +7,8 @@ namespace Magento\Quote\Api; +use Magento\Quote\Api\Data\CartItemInterface; + /** * Interface AddCartItemInterface * @api @@ -16,11 +18,11 @@ interface AddCartItemInterface /** * Add the specified cart item. * - * @param \Magento\Quote\Api\Data\CartItemInterface $cartItem The item. - * @return \Magento\Quote\Api\Data\CartItemInterface Item. + * @param CartItemInterface $cartItem The item. + * @return CartItemInterface Item. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist. * @throws \Magento\Framework\Exception\CouldNotSaveException The specified item could not be saved to the cart. * @throws \Magento\Framework\Exception\InputException The specified item or cart is not valid. */ - public function execute(\Magento\Quote\Api\Data\CartItemInterface $cartItem); + public function execute(CartItemInterface $cartItem): CartItemInterface; } diff --git a/app/code/Magento/Quote/Api/UpdateCartItemInterface.php b/app/code/Magento/Quote/Api/UpdateCartItemInterface.php index 5252297c23c81..5409eb6251dd1 100644 --- a/app/code/Magento/Quote/Api/UpdateCartItemInterface.php +++ b/app/code/Magento/Quote/Api/UpdateCartItemInterface.php @@ -7,6 +7,8 @@ namespace Magento\Quote\Api; +use Magento\Quote\Api\Data\CartItemInterface; + /** * Interface AddCartItemInterface * @api @@ -16,11 +18,11 @@ interface UpdateCartItemInterface /** * Update the specified cart item. * - * @param \Magento\Quote\Api\Data\CartItemInterface $cartItem The item. - * @return \Magento\Quote\Api\Data\CartItemInterface Item. + * @param CartItemInterface $cartItem The item. + * @return CartItemInterface Item. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist. * @throws \Magento\Framework\Exception\CouldNotSaveException The specified item could not be saved to the cart. * @throws \Magento\Framework\Exception\InputException The specified item or cart is not valid. */ - public function execute(\Magento\Quote\Api\Data\CartItemInterface $cartItem); + public function execute(CartItemInterface $cartItem): CartItemInterface; } diff --git a/app/code/Magento/Quote/Model/Quote/Item/AddCartItem.php b/app/code/Magento/Quote/Model/Quote/Item/AddCartItem.php index 7bea5d81b787f..d0ca3c9f1972c 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/AddCartItem.php +++ b/app/code/Magento/Quote/Model/Quote/Item/AddCartItem.php @@ -31,7 +31,7 @@ public function __construct(Repository $quoteItemRepository) /** * @inheritDoc */ - public function execute(CartItemInterface $cartItem) + public function execute(CartItemInterface $cartItem): CartItemInterface { if (isset($cartItem[CartItemInterface::KEY_ITEM_ID])) { unset($cartItem[CartItemInterface::KEY_ITEM_ID]); diff --git a/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php b/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php index fac1a0113477c..a36f1b5f1bd3a 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php +++ b/app/code/Magento/Quote/Model/Quote/Item/UpdateCartItem.php @@ -31,7 +31,7 @@ public function __construct(Repository $quoteItemRepository) /** * @inheritDoc */ - public function execute(CartItemInterface $cartItem) + public function execute(CartItemInterface $cartItem): CartItemInterface { return $this->quoteItemRepository->save($cartItem); } diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php new file mode 100644 index 0000000000000..ef9bb3b8b473a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php @@ -0,0 +1,103 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php + * @magentoApiDataFixture Magento/Bundle/_files/product.php + */ + public function testAddItem(): void + { + /** @var Product $product */ + $product = $this->objectManager->create(Product::class)->load(3); + $quote = $this->objectManager->create(Quote::class)->load( + 'test_order_item_with_items', + 'reserved_order_id' + ); + + $itemQty = 1; + $bundleProductOptions = $product->getExtensionAttributes()->getBundleProductOptions(); + $bundleOptionId = $bundleProductOptions[0]->getId(); + $optionSelections = $bundleProductOptions[0]->getProductLinks()[0]->getId(); + $buyRequest = [ + 'bundle_option' => [$bundleOptionId => [$optionSelections]], + 'bundle_option_qty' => [$bundleOptionId => 1], + 'qty' => $itemQty, + 'original_qty' => $itemQty + ]; + + $productSku = $product->getSku(); + $productId = $product->getId(); + /** @var Quote $quote */ + + $cartId = $quote->getId(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + $requestData = [ + "cartItem" => [ + "sku" => $productSku, + "qty" => $itemQty, + "quote_id" => $cartId, + "product_option" => [ + "extension_attributes" => [ + "bundle_options" => [ + [ + "option_id" => (int)$bundleOptionId, + "option_qty" => $itemQty, + "option_selections" => [(int)$optionSelections] + ] + ] + ] + ] + ] + ]; + $response = $this->_webApiCall($serviceInfo, $requestData); + $this->assertTrue($quote->hasProductId($productId)); + $this->assertEquals($buyRequest, $quote->getItemById($response['item_id'])->getBuyRequest()->getData()); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemRepositoryTest.php index a272481deba8a..4450263b9ebb1 100644 --- a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemRepositoryTest.php @@ -3,10 +3,19 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Bundle\Api; +use Magento\Framework\Webapi\Rest\Request; +use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * API test for cart item repository with bundle product. + */ class CartItemRepositoryTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; @@ -14,22 +23,25 @@ class CartItemRepositoryTest extends WebapiAbstract const RESOURCE_PATH = '/V1/carts/'; /** - * @var \Magento\TestFramework\ObjectManager + * @var ObjectManager */ protected $objectManager; + /** + * @inheritDoc + */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_bundle_and_options.php */ - public function testGetAll() + public function testGetAll(): void { - /** @var $quote \Magento\Quote\Model\Quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load( + /** @var $quote Quote */ + $quote = $this->objectManager->create(Quote::class)->load( 'test_order_bundle', 'reserved_order_id' ); @@ -38,7 +50,7 @@ public function testGetAll() $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . $quoteId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + 'httpMethod' => Request::HTTP_METHOD_GET, ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -61,146 +73,4 @@ public function testGetAll() $this->assertEquals($expectedSelections, $option['option_selections']); } } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php - * @magentoApiDataFixture Magento/Bundle/_files/product.php - */ - public function testAddItem() - { - /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class)->load(3); - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load( - 'test_order_item_with_items', - 'reserved_order_id' - ); - - $itemQty = 1; - $bundleProductOptions = $product->getExtensionAttributes()->getBundleProductOptions(); - $bundleOptionId = $bundleProductOptions[0]->getId(); - $optionSelections = $bundleProductOptions[0]->getProductLinks()[0]->getId(); - $buyRequest = [ - 'bundle_option' => [$bundleOptionId => [$optionSelections]], - 'bundle_option_qty' => [$bundleOptionId => 1], - 'qty' => $itemQty, - 'original_qty' => $itemQty - ]; - - $productSku = $product->getSku(); - $productId = $product->getId(); - /** @var \Magento\Quote\Model\Quote $quote */ - - $cartId = $quote->getId(); - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - $requestData = [ - "cartItem" => [ - "sku" => $productSku, - "qty" => $itemQty, - "quote_id" => $cartId, - "product_option" => [ - "extension_attributes" => [ - "bundle_options" => [ - [ - "option_id" => (int)$bundleOptionId, - "option_qty" => $itemQty, - "option_selections" => [(int)$optionSelections] - ] - ] - ] - ] - ] - ]; - $response = $this->_webApiCall($serviceInfo, $requestData); - $this->assertTrue($quote->hasProductId($productId)); - $this->assertEquals($buyRequest, $quote->getItemById($response['item_id'])->getBuyRequest()->getData()); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_bundle_and_options.php - */ - public function testUpdate() - { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load( - 'test_order_bundle', - 'reserved_order_id' - ); - $cartId = $quote->getId(); - $cartItem = $quote->getAllVisibleItems()[0]; - $itemSku = $cartItem->getSku(); - $itemId = $cartItem->getId(); - - $product = $cartItem->getProduct(); - /** @var $typeInstance \Magento\Bundle\Model\Product\Type */ - $typeInstance = $product->getTypeInstance(); - $typeInstance->setStoreFilter($product->getStoreId(), $product); - $optionCollection = $typeInstance->getOptionsCollection($product); - $bundleOptions = []; - /** @var $option \Magento\Bundle\Model\Option */ - foreach ($optionCollection as $option) { - if (!$option->getRequired()) { - continue; - } - $selectionsCollection = $typeInstance->getSelectionsCollection([$option->getId()], $product); - $option = ['option_id' => $option->getId(), 'option_qty' => 1]; - $option['option_selections'] = [$selectionsCollection->getLastItem()->getSelectionId()]; - $bundleOptions[] = $option; - } - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items/' . $itemId, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - $requestData = [ - "cartItem" => [ - "sku" => $itemSku, - "qty" => 2, - "quote_id" => $cartId, - "item_id" => $itemId, - "product_option" => [ - "extension_attributes" => [ - "bundle_options" => $bundleOptions - ] - ] - ] - ]; - $this->_webApiCall($serviceInfo, $requestData); - - $quoteUpdated = $this->objectManager->create(\Magento\Quote\Model\Quote::class)->load( - 'test_order_bundle', - 'reserved_order_id' - ); - $cartItems = $quoteUpdated->getAllVisibleItems(); - $buyRequest = $cartItems[0]->getBuyRequest()->toArray(); - - $this->assertCount(1, $cartItems); - $this->assertEquals(count($buyRequest['bundle_option']), count($bundleOptions)); - foreach ($bundleOptions as $option) { - $optionId = $option['option_id']; - $optionQty = $option['option_qty']; - $optionSelections = $option['option_selections']; - $this->assertArrayHasKey($optionId, $buyRequest['bundle_option']); - $this->assertEquals($optionQty, $buyRequest['bundle_option_qty'][$optionId]); - $this->assertEquals($optionSelections, $buyRequest['bundle_option'][$optionId]); - } - } } diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemUpdateTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemUpdateTest.php new file mode 100644 index 0000000000000..30f5b556deddb --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemUpdateTest.php @@ -0,0 +1,116 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_bundle_and_options.php + */ + public function testUpdate(): void + { + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class)->load( + 'test_order_bundle', + 'reserved_order_id' + ); + $cartId = $quote->getId(); + $cartItem = $quote->getAllVisibleItems()[0]; + $itemSku = $cartItem->getSku(); + $itemId = $cartItem->getId(); + + $product = $cartItem->getProduct(); + /** @var $typeInstance Type */ + $typeInstance = $product->getTypeInstance(); + $typeInstance->setStoreFilter($product->getStoreId(), $product); + $optionCollection = $typeInstance->getOptionsCollection($product); + $bundleOptions = []; + /** @var $option Option */ + foreach ($optionCollection as $option) { + if (!$option->getRequired()) { + continue; + } + $selectionsCollection = $typeInstance->getSelectionsCollection([$option->getId()], $product); + $option = ['option_id' => $option->getId(), 'option_qty' => 1]; + $option['option_selections'] = [$selectionsCollection->getLastItem()->getSelectionId()]; + $bundleOptions[] = $option; + } + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items/' . $itemId, + 'httpMethod' => Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + $requestData = [ + "cartItem" => [ + "sku" => $itemSku, + "qty" => 2, + "quote_id" => $cartId, + "item_id" => $itemId, + "product_option" => [ + "extension_attributes" => [ + "bundle_options" => $bundleOptions + ] + ] + ] + ]; + $this->_webApiCall($serviceInfo, $requestData); + + $quoteUpdated = $this->objectManager->create(Quote::class)->load( + 'test_order_bundle', + 'reserved_order_id' + ); + $cartItems = $quoteUpdated->getAllVisibleItems(); + $buyRequest = $cartItems[0]->getBuyRequest()->toArray(); + + $this->assertCount(1, $cartItems); + $this->assertEquals(count($buyRequest['bundle_option']), count($bundleOptions)); + foreach ($bundleOptions as $option) { + $optionId = $option['option_id']; + $optionQty = $option['option_qty']; + $optionSelections = $option['option_selections']; + $this->assertArrayHasKey($optionId, $buyRequest['bundle_option']); + $this->assertEquals($optionQty, $buyRequest['bundle_option_qty'][$optionId]); + $this->assertEquals($optionSelections, $buyRequest['bundle_option'][$optionId]); + } + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemAddTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemAddTest.php new file mode 100644 index 0000000000000..f760387b299df --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemAddTest.php @@ -0,0 +1,158 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testAddProductToCartWithCustomOptions(): void + { + $productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU); + + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_order_1', 'reserved_order_id'); + $cartId = $quote->getId(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + $response = $this->_webApiCall($serviceInfo, $this->getRequestData($cartId)); + $this->assertTrue($quote->hasProductId($product->getId())); + $this->assertCount(1, $quote->getAllItems()); + /** @var CartItemInterface $item */ + $item = $quote->getAllItems()[0]; + $this->assertEquals( + [ + 'item_id' => $item->getItemId(), + 'sku' => $item->getSku(), + 'qty' => $item->getQty(), + 'name' => $item->getName(), + 'price' => $item->getPrice(), + 'product_type' => $item->getProductType(), + 'quote_id' => $item->getQuoteId(), + 'product_option' => [ + 'extension_attributes' => [ + 'custom_options' => $this->getOptions(), + ], + ], + ], + $response + ); + } + + /** + * Receive product options with values + * + * @return array + */ + private function getOptions(): array + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU); + $options = []; + /** @var ProductCustomOptionInterface $option */ + foreach ($product->getOptions() as $option) { + $options[] = [ + 'option_id' => $option->getId(), + 'option_value' => $this->getOptionRequestValue($option), + ]; + } + + return $options; + } + + /** + * @param $cartId + * @return array + */ + private function getRequestData($cartId): array + { + return [ + 'cartItem' => [ + 'sku' => self::SIMPLE_PRODUCT_SKU, + 'qty' => 1, + 'quote_id' => $cartId, + 'product_option' => [ + 'extension_attributes' => [ + 'custom_options' => $this->getOptions(), + ], + ], + ], + ]; + } + + /** + * Receive option value based on option type + * + * @param ProductCustomOptionInterface $option + * @return null|string + */ + protected function getOptionRequestValue(ProductCustomOptionInterface $option) + { + $returnValue = null; + switch ($option->getType()) { + case 'field': + $returnValue = 'Test value'; + break; + case 'date_time': + $returnValue = '2015-09-09 07:16:00'; + break; + case 'drop_down': + $returnValue = '3-1-select'; + break; + case 'radio': + $returnValue = '4-1-radio'; + break; + } + return $returnValue; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php index e3680c573750d..dd28b55e78335 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php @@ -7,9 +7,11 @@ namespace Magento\Catalog\Api; +use Magento\Framework\Webapi\Rest\Request; +use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\WebapiAbstract; -use Magento\Catalog\Api\Data\ProductCustomOptionInterface; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; /** * Class \Magento\Catalog\Api\CartItemRepositoryTest @@ -21,79 +23,32 @@ class CartItemRepositoryTest extends WebapiAbstract const SIMPLE_PRODUCT_SKU = 'simple'; /** - * @var \Magento\TestFramework\ObjectManager + * @var ObjectManager */ protected $objectManager; - protected function setUp(): void - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - } - /** - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @inheritDoc */ - public function testAddProductToCartWithCustomOptions() + protected function setUp(): void { - $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - /** @var \Magento\Catalog\Api\Data\ProductInterface $product */ - $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU); - - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test_order_1', 'reserved_order_id'); - $cartId = $quote->getId(); - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - $response = $this->_webApiCall($serviceInfo, $this->getRequestData($cartId)); - $this->assertTrue($quote->hasProductId($product->getId())); - $this->assertCount(1, $quote->getAllItems()); - /** @var \Magento\Quote\Api\Data\CartItemInterface $item */ - $item = $quote->getAllItems()[0]; - $this->assertEquals( - [ - 'item_id' => $item->getItemId(), - 'sku' => $item->getSku(), - 'qty' => $item->getQty(), - 'name' => $item->getName(), - 'price' => $item->getPrice(), - 'product_type' => $item->getProductType(), - 'quote_id' => $item->getQuoteId(), - 'product_option' => [ - 'extension_attributes' => [ - 'custom_options' => $this->getOptions(), - ], - ], - ], - $response - ); + $this->objectManager = Bootstrap::getObjectManager(); } /** * @magentoApiDataFixture Magento/Catalog/_files/quote_with_product_and_custom_options.php */ - public function testGetList() + public function testGetList(): void { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); $quote->load('test_order_1', 'reserved_order_id'); $cartId = $quote->getId(); $serviceInfo = [ 'rest' => [ 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET + 'httpMethod' => Request::HTTP_METHOD_GET ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -115,72 +70,4 @@ public function testGetList() $this->assertArrayHasKey('option_id', $option); $this->assertArrayHasKey('option_value', $option); } - - /** - * Receive product options with values - * - * @return array - */ - protected function getOptions() - { - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $product = $productRepository->get(self::SIMPLE_PRODUCT_SKU); - $options = []; - /** @var ProductCustomOptionInterface $option */ - foreach ($product->getOptions() as $option) { - $options[] = [ - 'option_id' => $option->getId(), - 'option_value' => $this->getOptionRequestValue($option), - ]; - } - - return $options; - } - - /** - * @param $cartId - * @return array - */ - protected function getRequestData($cartId) - { - return [ - 'cartItem' => [ - 'sku' => self::SIMPLE_PRODUCT_SKU, - 'qty' => 1, - 'quote_id' => $cartId, - 'product_option' => [ - 'extension_attributes' => [ - 'custom_options' => $this->getOptions(), - ], - ], - ], - ]; - } - - /** - * Receive option value based on option type - * - * @param ProductCustomOptionInterface $option - * @return null|string - */ - protected function getOptionRequestValue(ProductCustomOptionInterface $option) - { - $returnValue = null; - switch ($option->getType()) { - case 'field': - $returnValue = 'Test value'; - break; - case 'date_time': - $returnValue = '2015-09-09 07:16:00'; - break; - case 'drop_down': - $returnValue = '3-1-select'; - break; - case 'radio': - $returnValue = '4-1-radio'; - break; - } - return $returnValue; - } } diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemAddTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemAddTest.php new file mode 100644 index 0000000000000..62f123794fffe --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemAddTest.php @@ -0,0 +1,159 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php + */ + public function testAddProduct(): void + { + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_order_1', 'reserved_order_id'); + $cartId = $quote->getId(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + $response = $this->_webApiCall($serviceInfo, $this->getRequestData($cartId)); + $this->assertNotNull($response['item_id']); + $this->assertEquals(Configurable::TYPE_CODE, $response['product_type']); + + $quote->load('test_order_1', 'reserved_order_id'); + $items = $quote->getAllItems(); + $this->assertGreaterThan(0, count($items)); + + /** @var \Magento\Quote\Model\ResourceModel\Quote\Item|null $item */ + $item = null; + /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $quoteItem */ + foreach ($items as $quoteItem) { + if ($quoteItem->getProductType() == Configurable::TYPE_CODE && !$quoteItem->getParentItemId()) { + $item = $quoteItem; + break; + } + } + $this->assertNotNull($item); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php + */ + public function testAddProductWithIncorrectOptions(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('You need to choose options for your item.'); + + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_order_1', 'reserved_order_id'); + $cartId = $quote->getId(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + $requestData = $this->getRequestData($cartId); + $requestData['cartItem']['product_option']['extension_attributes'] + ['configurable_item_options'][0]['option_id'] = 1000; + + $requestData['cartItem']['product_option']['extension_attributes'] + ['configurable_item_options'][0]['option_value'] = 2000; + + $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @param $cartId + * @param null $selectedOption + * @return array + */ + protected function getRequestData($cartId, $selectedOption = null): array + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $product = $productRepository->get(self::CONFIGURABLE_PRODUCT_SKU); + + $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions(); + + $optionKey = 0; + if ($selectedOption && isset($options[$selectedOption])) { + $optionKey = $selectedOption; + } + + $attributeId = $configurableProductOptions[0]->getAttributeId(); + $options = $configurableProductOptions[0]->getOptions(); + $optionId = $options[$optionKey]['value_index']; + + return [ + 'cartItem' => [ + 'sku' => self::CONFIGURABLE_PRODUCT_SKU, + 'qty' => 1, + 'quote_id' => $cartId, + 'product_option' => [ + 'extension_attributes' => [ + 'configurable_item_options' => [ + [ + 'option_id' => $attributeId, + 'option_value' => $optionId + ] + ] + ] + ] + ] + ]; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php index eb8da6e02ad07..2f5d2cb58e53a 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemRepositoryTest.php @@ -3,12 +3,20 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\ConfigurableProduct\Api; +use Magento\Framework\Webapi\Rest\Request; +use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\WebapiAbstract; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; +/** + * API test for cart item repository with configurable product. + */ class CartItemRepositoryTest extends WebapiAbstract { const SERVICE_NAME = 'quoteCartItemRepositoryV1'; @@ -16,266 +24,16 @@ class CartItemRepositoryTest extends WebapiAbstract const CONFIGURABLE_PRODUCT_SKU = 'configurable'; /** - * @var \Magento\TestFramework\ObjectManager + * @var ObjectManager */ protected $objectManager; - protected function setUp(): void - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php - */ - public function testAddProduct() - { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test_order_1', 'reserved_order_id'); - $cartId = $quote->getId(); - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - $response = $this->_webApiCall($serviceInfo, $this->getRequestData($cartId)); - $this->assertNotNull($response['item_id']); - $this->assertEquals(Configurable::TYPE_CODE, $response['product_type']); - - $quote->load('test_order_1', 'reserved_order_id'); - $items = $quote->getAllItems(); - $this->assertGreaterThan(0, count($items)); - - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item|null $item */ - $item = null; - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $quoteItem */ - foreach ($items as $quoteItem) { - if ($quoteItem->getProductType() == Configurable::TYPE_CODE && !$quoteItem->getParentItemId()) { - $item = $quoteItem; - break; - } - } - $this->assertNotNull($item); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php - */ - public function testAddProductWithIncorrectOptions() - { - $this->expectException(\Exception::class); - $this->expectExceptionMessage('You need to choose options for your item.'); - - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test_order_1', 'reserved_order_id'); - $cartId = $quote->getId(); - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - $requestData = $this->getRequestData($cartId); - $requestData['cartItem']['product_option']['extension_attributes'] - ['configurable_item_options'][0]['option_id'] = 1000; - - $requestData['cartItem']['product_option']['extension_attributes'] - ['configurable_item_options'][0]['option_value'] = 2000; - - $this->_webApiCall($serviceInfo, $requestData); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php - */ - public function testUpdateIncorrectItem() - { - $this->expectException(\Exception::class); - $this->expectExceptionMessage('The %1 Cart doesn\'t contain the %2 item.'); - - $qty = 1; - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test_cart_with_configurable', 'reserved_order_id'); - $cartId = $quote->getId(); - - $requestData = $this->getRequestData($cartId, 1); - $requestData['cartItem']['qty'] = $qty; - $requestData['cartItem']['item_id'] = 1000; - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items/1000', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - $this->_webApiCall($serviceInfo, $requestData); - } - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php + * @inheritDoc */ - public function testUpdate() - { - $qty = 4; - $this->updateStockForItem(10, 100); - $this->updateStockForItem(20, 100); - - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test_cart_with_configurable', 'reserved_order_id'); - $cartId = $quote->getId(); - - $items = $quote->getAllItems(); - $this->assertGreaterThan(0, count($items)); - - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item|null $item */ - $item = null; - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $quoteItem */ - foreach ($items as $quoteItem) { - if ($quoteItem->getProductType() == Configurable::TYPE_CODE) { - $item = $quoteItem; - break; - } - } - - $this->assertNotNull($item); - $this->assertNotNull($item->getId()); - $this->assertEquals(Configurable::TYPE_CODE, $item->getProductType()); - - $requestData = $this->getRequestData($cartId, 1); - $requestData['cartItem']['qty'] = $qty; - $requestData['cartItem']['item_id'] = $item->getId(); - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $item->getId(), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - $response = $this->_webApiCall($serviceInfo, $requestData); - - $this->assertNotNull($response['item_id']); - $this->assertEquals(Configurable::TYPE_CODE, $response['product_type']); - $this->assertEquals($cartId, $response['quote_id']); - $this->assertEquals($qty, $response['qty']); - $this->assertEquals( - $response['product_option']['extension_attributes']['configurable_item_options'][0], - $requestData['cartItem']['product_option']['extension_attributes']['configurable_item_options'][0] - ); - } - - /** - * @param int $itemId - * @param int $qty - */ - protected function updateStockForItem($itemId, $qty) - { - /** @var \Magento\CatalogInventory\Model\Stock\Status $stockStatus */ - $stockStatus = $this->objectManager->create(\Magento\CatalogInventory\Model\Stock\Status::class); - $stockStatus->load($itemId, 'product_id'); - if (!$stockStatus->getProductId()) { - $stockStatus->setProductId($itemId); - } - $stockStatus->setQty($qty); - $stockStatus->setStockStatus(1); - $stockStatus->save(); - - /** @var \Magento\CatalogInventory\Model\Stock\Item $stockItem */ - $stockItem = $this->objectManager->create(\Magento\CatalogInventory\Model\Stock\Item::class); - $stockItem->load($itemId, 'product_id'); - - if (!$stockItem->getProductId()) { - $stockItem->setProductId($itemId); - } - $stockItem->setUseConfigManageStock(1); - $stockItem->setQty($qty); - $stockItem->setIsQtyDecimal(0); - $stockItem->setIsInStock(1); - $stockItem->save(); - } - - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php - */ - public function testUpdateQty() + protected function setUp(): void { - $qty = 1; - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('test_cart_with_configurable', 'reserved_order_id'); - $cartId = $quote->getId(); - - $items = $quote->getAllItems(); - $this->assertGreaterThan(0, count($items)); - - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item|null $item */ - $item = null; - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $quoteItem */ - foreach ($items as $quoteItem) { - if ($quoteItem->getProductType() == Configurable::TYPE_CODE) { - $item = $quoteItem; - break; - } - } - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $item->getId(), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - $this->assertNotNull($item); - $this->assertNotNull($item->getId()); - $this->assertEquals(Configurable::TYPE_CODE, $item->getProductType()); - - $requestData = $this->getRequestData($cartId); - $requestData['cartItem']['qty'] = $qty; - $requestData['cartItem']['item_id'] = $item->getId(); - $requestData['cartItem']['product_option'] = null; - - $response = $this->_webApiCall($serviceInfo, $requestData); - - $this->assertNotNull($response['item_id']); - $this->assertEquals($item->getId(), $response['item_id']); - $this->assertEquals(Configurable::TYPE_CODE, $response['product_type']); - $this->assertEquals($cartId, $response['quote_id']); - $this->assertEquals($qty, $response['qty']); + $this->objectManager = Bootstrap::getObjectManager(); } /** @@ -283,15 +41,15 @@ public function testUpdateQty() */ public function testGetList() { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); $quote->load('test_cart_with_configurable', 'reserved_order_id'); $cartId = $quote->getId(); $serviceInfo = [ 'rest' => [ 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET + 'httpMethod' => Request::HTTP_METHOD_GET ], 'soap' => [ 'service' => self::SERVICE_NAME, @@ -319,45 +77,4 @@ public function testGetList() $this->assertNotNull($options[0]['option_id']); $this->assertNotNull($options[0]['option_value']); } - - /** - * @param $cartId - * @param null $selectedOption - * @return array - */ - protected function getRequestData($cartId, $selectedOption = null) - { - /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ - $productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); - $product = $productRepository->get(self::CONFIGURABLE_PRODUCT_SKU); - - $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions(); - - $optionKey = 0; - if ($selectedOption && isset($options[$selectedOption])) { - $optionKey = $selectedOption; - } - - $attributeId = $configurableProductOptions[0]->getAttributeId(); - $options = $configurableProductOptions[0]->getOptions(); - $optionId = $options[$optionKey]['value_index']; - - return [ - 'cartItem' => [ - 'sku' => self::CONFIGURABLE_PRODUCT_SKU, - 'qty' => 1, - 'quote_id' => $cartId, - 'product_option' => [ - 'extension_attributes' => [ - 'configurable_item_options' => [ - [ - 'option_id' => $attributeId, - 'option_value' => $optionId - ] - ] - ] - ] - ] - ]; - } } diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemUpdateTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemUpdateTest.php new file mode 100644 index 0000000000000..9392fc06c3504 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/CartItemUpdateTest.php @@ -0,0 +1,257 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php + */ + public function testUpdate(): void + { + $qty = 4; + $this->updateStockForItem(10, 100); + $this->updateStockForItem(20, 100); + + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_cart_with_configurable', 'reserved_order_id'); + $cartId = $quote->getId(); + + $items = $quote->getAllItems(); + $this->assertGreaterThan(0, count($items)); + + /** @var Item|null $item */ + $item = null; + /** @var Item $quoteItem */ + foreach ($items as $quoteItem) { + if ($quoteItem->getProductType() == Configurable::TYPE_CODE) { + $item = $quoteItem; + break; + } + } + + $this->assertNotNull($item); + $this->assertNotNull($item->getId()); + $this->assertEquals(Configurable::TYPE_CODE, $item->getProductType()); + + $requestData = $this->getRequestData($cartId, 1); + $requestData['cartItem']['qty'] = $qty; + $requestData['cartItem']['item_id'] = $item->getId(); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $item->getId(), + 'httpMethod' => Request::HTTP_METHOD_PUT + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + $response = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertNotNull($response['item_id']); + $this->assertEquals(Configurable::TYPE_CODE, $response['product_type']); + $this->assertEquals($cartId, $response['quote_id']); + $this->assertEquals($qty, $response['qty']); + $this->assertEquals( + $response['product_option']['extension_attributes']['configurable_item_options'][0], + $requestData['cartItem']['product_option']['extension_attributes']['configurable_item_options'][0] + ); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php + */ + public function testUpdateQty(): void + { + $qty = 1; + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_cart_with_configurable', 'reserved_order_id'); + $cartId = $quote->getId(); + + $items = $quote->getAllItems(); + $this->assertGreaterThan(0, count($items)); + + /** @var Item|null $item */ + $item = null; + /** @var Item $quoteItem */ + foreach ($items as $quoteItem) { + if ($quoteItem->getProductType() == Configurable::TYPE_CODE) { + $item = $quoteItem; + break; + } + } + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $item->getId(), + 'httpMethod' => Request::HTTP_METHOD_PUT + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + $this->assertNotNull($item); + $this->assertNotNull($item->getId()); + $this->assertEquals(Configurable::TYPE_CODE, $item->getProductType()); + + $requestData = $this->getRequestData($cartId); + $requestData['cartItem']['qty'] = $qty; + $requestData['cartItem']['item_id'] = $item->getId(); + $requestData['cartItem']['product_option'] = null; + + $response = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertNotNull($response['item_id']); + $this->assertEquals($item->getId(), $response['item_id']); + $this->assertEquals(Configurable::TYPE_CODE, $response['product_type']); + $this->assertEquals($cartId, $response['quote_id']); + $this->assertEquals($qty, $response['qty']); + } + + /** + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/quote_with_configurable_product.php + */ + public function testUpdateIncorrectItem(): void + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('The %1 Cart doesn\'t contain the %2 item.'); + + $qty = 1; + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_cart_with_configurable', 'reserved_order_id'); + $cartId = $quote->getId(); + + $requestData = $this->getRequestData($cartId, 1); + $requestData['cartItem']['qty'] = $qty; + $requestData['cartItem']['item_id'] = 1000; + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items/1000', + 'httpMethod' => Request::HTTP_METHOD_PUT + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @param int $itemId + * @param int $qty + */ + private function updateStockForItem($itemId, $qty): void + { + /** @var Status $stockStatus */ + $stockStatus = $this->objectManager->create(Status::class); + $stockStatus->load($itemId, 'product_id'); + if (!$stockStatus->getProductId()) { + $stockStatus->setProductId($itemId); + } + $stockStatus->setQty($qty); + $stockStatus->setStockStatus(1); + $stockStatus->save(); + + /** @var StockItem $stockItem */ + $stockItem = $this->objectManager->create(StockItem::class); + $stockItem->load($itemId, 'product_id'); + + if (!$stockItem->getProductId()) { + $stockItem->setProductId($itemId); + } + $stockItem->setUseConfigManageStock(1); + $stockItem->setQty($qty); + $stockItem->setIsQtyDecimal(0); + $stockItem->setIsInStock(1); + $stockItem->save(); + } + + /** + * @param $cartId + * @param null $selectedOption + * @return array + */ + private function getRequestData($cartId, $selectedOption = null): array + { + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->create(ProductRepositoryInterface::class); + $product = $productRepository->get(self::CONFIGURABLE_PRODUCT_SKU); + + $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions(); + + $optionKey = 0; + if ($selectedOption && isset($options[$selectedOption])) { + $optionKey = $selectedOption; + } + + $attributeId = $configurableProductOptions[0]->getAttributeId(); + $options = $configurableProductOptions[0]->getOptions(); + $optionId = $options[$optionKey]['value_index']; + + return [ + 'cartItem' => [ + 'sku' => self::CONFIGURABLE_PRODUCT_SKU, + 'qty' => 1, + 'quote_id' => $cartId, + 'product_option' => [ + 'extension_attributes' => [ + 'configurable_item_options' => [ + [ + 'option_id' => $attributeId, + 'option_value' => $optionId + ] + ] + ] + ] + ] + ]; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemAddTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemAddTest.php new file mode 100644 index 0000000000000..b84960e78c777 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemAddTest.php @@ -0,0 +1,139 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php + * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php + */ + public function testAddItem(): void + { + /** @var Product $product */ + $product = $this->objectManager->create(Product::class)->load(1); + $productSku = $product->getSku(); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('reserved_order_id', 'reserved_order_id'); + $cartId = $quote->getId(); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + // use ID of the first downloadable link + $linkId = array_values($product->getDownloadableLinks())[0]->getId(); + + $requestData = [ + 'cartItem' => [ + 'sku' => $productSku, + 'qty' => 1, + 'quote_id' => $cartId, + 'product_option' => [ + 'extension_attributes' => [ + 'downloadable_option' => [ + 'downloadable_links' => [$linkId] + ] + ] + ] + ], + ]; + $response = $this->_webApiCall($serviceInfo, $requestData); + $this->assertNotEmpty($response); + $this->assertEquals('downloadable-product', $response['sku']); + $this->assertEquals(1, $response['qty']); + $this->assertCount( + 1, + $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] + ); + $this->assertContainsEquals( + $linkId, + $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] + ); + } + + /** + * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php + * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php + */ + public function testAddItemWithInvalidLinkId(): void + { + $this->expectException(\Exception::class); + + /** @var Product $product */ + $product = $this->objectManager->create(Product::class)->load(1); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('reserved_order_id', 'reserved_order_id'); + $cartId = $quote->getId(); + $productSku = $product->getSku(); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + $linkId = 9999; + + $requestData = [ + 'cartItem' => [ + 'sku' => $productSku, + 'qty' => 1, + 'quote_id' => $cartId, + 'product_option' => [ + 'extension_attributes' => [ + 'downloadable_option' => [ + 'downloadable_links' => [$linkId] + ] + ] + ] + ], + ]; + $this->_webApiCall($serviceInfo, $requestData); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemRepositoryTest.php index 8af1d2a02d4e6..cbb7d8c85e7f9 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemRepositoryTest.php @@ -3,229 +3,35 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Downloadable\Api; +use Magento\Quote\Api\Data\CartItemInterface; +use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * API test for cart item repository with downloadable product. + */ class CartItemRepositoryTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; const SERVICE_NAME = 'quoteCartItemRepositoryV1'; /** - * @var \Magento\TestFramework\ObjectManager + * @var ObjectManager */ protected $objectManager; - protected function setUp(): void - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - } - - /** - * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php - * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php - */ - public function testAddItem() - { - /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class)->load(1); - $productSku = $product->getSku(); - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('reserved_order_id', 'reserved_order_id'); - $cartId = $quote->getId(); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - // use ID of the first downloadable link - $linkId = array_values($product->getDownloadableLinks())[0]->getId(); - - $requestData = [ - 'cartItem' => [ - 'sku' => $productSku, - 'qty' => 1, - 'quote_id' => $cartId, - 'product_option' => [ - 'extension_attributes' => [ - 'downloadable_option' => [ - 'downloadable_links' => [$linkId] - ] - ] - ] - ], - ]; - $response = $this->_webApiCall($serviceInfo, $requestData); - $this->assertNotEmpty($response); - $this->assertEquals('downloadable-product', $response['sku']); - $this->assertEquals(1, $response['qty']); - $this->assertCount( - 1, - $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] - ); - $this->assertContainsEquals( - $linkId, - $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] - ); - } - - /** - * @magentoApiDataFixture Magento/Quote/_files/empty_quote.php - * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable.php - */ - public function testAddItemWithInvalidLinkId() - { - $this->expectException(\Exception::class); - - /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class)->load(1); - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('reserved_order_id', 'reserved_order_id'); - $cartId = $quote->getId(); - $productSku = $product->getSku(); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - $linkId = 9999; - - $requestData = [ - 'cartItem' => [ - 'sku' => $productSku, - 'qty' => 1, - 'quote_id' => $cartId, - 'product_option' => [ - 'extension_attributes' => [ - 'downloadable_option' => [ - 'downloadable_links' => [$linkId] - ] - ] - ] - ], - ]; - $this->_webApiCall($serviceInfo, $requestData); - } - /** - * @magentoApiDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php + * @inheritDoc */ - public function testUpdateItem() - { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('reserved_order_id_1', 'reserved_order_id'); - $cartId = $quote->getId(); - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); - $product->load($product->getIdBySku('downloadable-product')); - // use ID of the first quote item - $itemId = $quote->getAllItems()[0]->getId(); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $itemId, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - // use ID of the first downloadable link - $linkId = array_values($product->getDownloadableLinks())[0]->getId(); - - $requestData = [ - 'cartItem' => [ - 'qty' => 2, - 'quote_id' => $cartId, - 'item_id' => $itemId, - 'sku' => 'downloadable-product', - 'product_option' => [ - 'extension_attributes' => [ - 'downloadable_option' => [ - 'downloadable_links' => [$linkId] - ] - ] - ] - ], - ]; - $response = $this->_webApiCall($serviceInfo, $requestData); - $this->assertNotEmpty($response); - $this->assertEquals('downloadable-product', $response['sku']); - $this->assertEquals(2, $response['qty']); - $this->assertCount( - 1, - $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] - ); - $this->assertContainsEquals( - $linkId, - $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] - ); - } - - /** - * @magentoApiDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php - */ - public function testUpdateItemWithInvalidLinkId() + protected function setUp(): void { - $this->expectException(\Exception::class); - - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('reserved_order_id_1', 'reserved_order_id'); - $cartId = $quote->getId(); - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); - $product->load($product->getIdBySku('downloadable-product')); - // use ID of the first quote item - $itemId = $quote->getAllItems()[0]->getId(); - $serviceInfo = [ - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $itemId, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, - ], - ]; - - $linkId = 9999; - - $requestData = [ - 'cartItem' => [ - 'qty' => 2, - 'quote_id' => $cartId, - 'item_id' => $itemId, - 'sku' => 'downloadable-product', - 'product_option' => [ - 'extension_attributes' => [ - 'downloadable_option' => [ - 'downloadable_links' => [$linkId] - ] - ] - ] - ], - ]; - $this->_webApiCall($serviceInfo, $requestData); + $this->objectManager = Bootstrap::getObjectManager(); } /** @@ -233,8 +39,8 @@ public function testUpdateItemWithInvalidLinkId() */ public function testGetList() { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); $quote->load('reserved_order_id_1', 'reserved_order_id'); $cartId = $quote->getId(); $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); @@ -242,7 +48,7 @@ public function testGetList() // use ID of the first downloadable link $linkId = array_values($product->getDownloadableLinks())[0]->getId(); - /** @var \Magento\Quote\Api\Data\CartItemInterface $item */ + /** @var CartItemInterface $item */ $item = $quote->getAllItems()[0]; $expectedResult = [[ 'item_id' => $item->getItemId(), @@ -276,54 +82,4 @@ public function testGetList() $requestData = ["cartId" => $cartId]; $this->assertEquals($expectedResult, $this->_webApiCall($serviceInfo, $requestData)); } - - /** - * @magentoApiDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php - */ - public function testUpdateItemQty() - { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class); - $quote->load('reserved_order_id_1', 'reserved_order_id'); - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); - $product->load($product->getIdBySku('downloadable-product')); - $cartId = $quote->getId(); - // use ID of the first quote item - $itemId = $quote->getAllItems()[0]->getId(); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $itemId, - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - // use ID of the first downloadable link - $linkId = array_values($product->getDownloadableLinks())[0]->getId(); - - $requestData = [ - 'cartItem' => [ - 'qty' => 2, - 'quote_id' => $cartId, - 'item_id' => $itemId, - 'sku' => 'downloadable-product', - ], - ]; - $response = $this->_webApiCall($serviceInfo, $requestData); - $this->assertNotEmpty($response); - $this->assertEquals('downloadable-product', $response['sku']); - $this->assertEquals(2, $response['qty']); - $this->assertCount( - 1, - $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] - ); - $this->assertContainsEquals( - $linkId, - $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] - ); - } } diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemUpdateTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemUpdateTest.php new file mode 100644 index 0000000000000..391cb29c67423 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/CartItemUpdateTest.php @@ -0,0 +1,191 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php + */ + public function testUpdateItem(): void + { + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('reserved_order_id_1', 'reserved_order_id'); + $cartId = $quote->getId(); + $product = $this->objectManager->create(Product::class); + $product->load($product->getIdBySku('downloadable-product')); + // use ID of the first quote item + $itemId = $quote->getAllItems()[0]->getId(); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $itemId, + 'httpMethod' => Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + // use ID of the first downloadable link + $linkId = array_values($product->getDownloadableLinks())[0]->getId(); + + $requestData = [ + 'cartItem' => [ + 'qty' => 2, + 'quote_id' => $cartId, + 'item_id' => $itemId, + 'sku' => 'downloadable-product', + 'product_option' => [ + 'extension_attributes' => [ + 'downloadable_option' => [ + 'downloadable_links' => [$linkId] + ] + ] + ] + ], + ]; + $response = $this->_webApiCall($serviceInfo, $requestData); + $this->assertNotEmpty($response); + $this->assertEquals('downloadable-product', $response['sku']); + $this->assertEquals(2, $response['qty']); + $this->assertCount( + 1, + $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] + ); + $this->assertContainsEquals( + $linkId, + $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] + ); + } + + /** + * @magentoApiDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php + */ + public function testUpdateItemWithInvalidLinkId(): void + { + $this->expectException(\Exception::class); + + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('reserved_order_id_1', 'reserved_order_id'); + $cartId = $quote->getId(); + $product = $this->objectManager->create(Product::class); + $product->load($product->getIdBySku('downloadable-product')); + // use ID of the first quote item + $itemId = $quote->getAllItems()[0]->getId(); + $serviceInfo = [ + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $itemId, + 'httpMethod' => Request::HTTP_METHOD_PUT, + ], + ]; + + $linkId = 9999; + + $requestData = [ + 'cartItem' => [ + 'qty' => 2, + 'quote_id' => $cartId, + 'item_id' => $itemId, + 'sku' => 'downloadable-product', + 'product_option' => [ + 'extension_attributes' => [ + 'downloadable_option' => [ + 'downloadable_links' => [$linkId] + ] + ] + ] + ], + ]; + $this->_webApiCall($serviceInfo, $requestData); + } + + /** + * @magentoApiDataFixture Magento/Downloadable/_files/quote_with_downloadable_product.php + */ + public function testUpdateItemQty(): void + { + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('reserved_order_id_1', 'reserved_order_id'); + $product = $this->objectManager->create(Product::class); + $product->load($product->getIdBySku('downloadable-product')); + $cartId = $quote->getId(); + // use ID of the first quote item + $itemId = $quote->getAllItems()[0]->getId(); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/carts/' . $cartId . '/items/' . $itemId, + 'httpMethod' => Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + // use ID of the first downloadable link + $linkId = array_values($product->getDownloadableLinks())[0]->getId(); + + $requestData = [ + 'cartItem' => [ + 'qty' => 2, + 'quote_id' => $cartId, + 'item_id' => $itemId, + 'sku' => 'downloadable-product', + ], + ]; + $response = $this->_webApiCall($serviceInfo, $requestData); + $this->assertNotEmpty($response); + $this->assertEquals('downloadable-product', $response['sku']); + $this->assertEquals(2, $response['qty']); + $this->assertCount( + 1, + $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] + ); + $this->assertContainsEquals( + $linkId, + $response['product_option']['extension_attributes']['downloadable_option']['downloadable_links'] + ); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemAddTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemAddTest.php new file mode 100644 index 0000000000000..aaaa829ce2045 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemAddTest.php @@ -0,0 +1,76 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/Catalog/_files/product_without_options.php + */ + public function testAddItem(): void + { + /** @var Product $product */ + $product = $this->objectManager->create(Product::class)->load(2); + $productSku = $product->getSku(); + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_order_1', 'reserved_order_id'); + $cartId = $quote->getId(); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items', + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + $requestData = [ + "cartItem" => [ + "sku" => $productSku, + "qty" => 7, + "quote_id" => $cartId, + ], + ]; + $this->_webApiCall($serviceInfo, $requestData); + $this->assertTrue($quote->hasProductId(2)); + $this->assertEquals(7, $quote->getItemByProduct($product)->getQty()); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemRepositoryTest.php index bf5421b5ca2be..9a8411366ac48 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemRepositoryTest.php @@ -4,13 +4,22 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Quote\Api; use Magento\Catalog\Model\CustomOptions\CustomOptionProcessor; +use Magento\Catalog\Model\Product; use Magento\Framework\Webapi\Rest\Request; +use Magento\Quote\Api\Data\CartItemInterface; use Magento\Quote\Model\Quote; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\WebapiAbstract; +/** + * API test for cart item repository + */ class CartItemRepositoryTest extends WebapiAbstract { const SERVICE_VERSION = 'V1'; @@ -18,13 +27,16 @@ class CartItemRepositoryTest extends WebapiAbstract const RESOURCE_PATH = '/V1/carts/'; /** - * @var \Magento\TestFramework\ObjectManager + * @var ObjectManager */ protected $objectManager; + /** + * @inheritDoc + */ protected function setUp(): void { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->objectManager = Bootstrap::getObjectManager(); } /** @@ -39,7 +51,7 @@ public function testGetList() $output = []; $customOptionProcessor = $this->objectManager->get(CustomOptionProcessor::class); - /** @var \Magento\Quote\Api\Data\CartItemInterface $item */ + /** @var CartItemInterface $item */ foreach ($quote->getAllItems() as $item) { $customOptionProcessor->processOptions($item); $data = [ @@ -77,43 +89,6 @@ public function testGetList() $this->assertEquals($output, $this->_webApiCall($serviceInfo, $requestData)); } - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - * @magentoApiDataFixture Magento/Catalog/_files/product_without_options.php - */ - public function testAddItem() - { - /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class)->load(2); - $productSku = $product->getSku(); - /** @var Quote $quote */ - $quote = $this->objectManager->create(Quote::class); - $quote->load('test_order_1', 'reserved_order_id'); - $cartId = $quote->getId(); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items', - 'httpMethod' => Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - $requestData = [ - "cartItem" => [ - "sku" => $productSku, - "qty" => 7, - "quote_id" => $cartId, - ], - ]; - $this->_webApiCall($serviceInfo, $requestData); - $this->assertTrue($quote->hasProductId(2)); - $this->assertEquals(7, $quote->getItemByProduct($product)->getQty()); - } - /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php */ @@ -123,7 +98,7 @@ public function testRemoveItem() $quote = $this->objectManager->create(Quote::class); $quote->load('test_order_item_with_items', 'reserved_order_id'); $cartId = $quote->getId(); - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); + $product = $this->objectManager->create(Product::class); $productId = $product->getIdBySku('simple_one'); $product->load($productId); $itemId = $quote->getItemByProduct($product)->getId(); @@ -148,54 +123,4 @@ public function testRemoveItem() $quote->load('test_order_item_with_items', 'reserved_order_id'); $this->assertFalse($quote->hasProductId($productId)); } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php - */ - public function testUpdateItem() - { - /** @var Quote $quote */ - $quote = $this->objectManager->create(Quote::class); - $quote->load('test_order_item_with_items', 'reserved_order_id'); - $cartId = $quote->getId(); - $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); - $productId = $product->getIdBySku('simple_one'); - $product->load($productId); - $itemId = $quote->getItemByProduct($product)->getId(); - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items/' . $itemId, - 'httpMethod' => Request::HTTP_METHOD_PUT, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'Save', - ], - ]; - - if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { - $requestData = [ - "cartItem" => [ - "qty" => 5, - "quote_id" => $cartId, - "itemId" => $itemId, - ], - ]; - } else { - $requestData = [ - "cartItem" => [ - "qty" => 5, - "quote_id" => $cartId, - ], - ]; - } - $this->_webApiCall($serviceInfo, $requestData); - $quote = $this->objectManager->create(Quote::class); - $quote->load('test_order_item_with_items', 'reserved_order_id'); - $this->assertTrue($quote->hasProductId(1)); - $item = $quote->getItemByProduct($product); - $this->assertEquals(5, $item->getQty()); - $this->assertEquals($itemId, $item->getItemId()); - } } diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemUpdateTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemUpdateTest.php new file mode 100644 index 0000000000000..58e1813dabf68 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartItemUpdateTest.php @@ -0,0 +1,89 @@ +objectManager = Bootstrap::getObjectManager(); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php + */ + public function testUpdateItem(): void + { + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_order_item_with_items', 'reserved_order_id'); + $cartId = $quote->getId(); + $product = $this->objectManager->create(Product::class); + $productId = $product->getIdBySku('simple_one'); + $product->load($productId); + $itemId = $quote->getItemByProduct($product)->getId(); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . $cartId . '/items/' . $itemId, + 'httpMethod' => Request::HTTP_METHOD_PUT, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Execute', + ], + ]; + + if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) { + $requestData = [ + "cartItem" => [ + "qty" => 5, + "quote_id" => $cartId, + "itemId" => $itemId, + ], + ]; + } else { + $requestData = [ + "cartItem" => [ + "qty" => 5, + "quote_id" => $cartId, + ], + ]; + } + $this->_webApiCall($serviceInfo, $requestData); + $quote = $this->objectManager->create(Quote::class); + $quote->load('test_order_item_with_items', 'reserved_order_id'); + $this->assertTrue($quote->hasProductId(1)); + $item = $quote->getItemByProduct($product); + $this->assertEquals(5, $item->getQty()); + $this->assertEquals($itemId, $item->getItemId()); + } +} From 831b6f149b686bcc9ace653c2b6ec7f69f04c901 Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Mon, 25 Jan 2021 18:34:04 +0200 Subject: [PATCH 5/6] MC-34298: Introduce separate POST and PUT API for carts/mine/items --- app/code/Magento/Quote/Api/AddCartItemInterface.php | 4 ++-- app/code/Magento/Quote/Api/UpdateCartItemInterface.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Quote/Api/AddCartItemInterface.php b/app/code/Magento/Quote/Api/AddCartItemInterface.php index dc50cd1e882ae..cea3d3e8bee16 100644 --- a/app/code/Magento/Quote/Api/AddCartItemInterface.php +++ b/app/code/Magento/Quote/Api/AddCartItemInterface.php @@ -18,8 +18,8 @@ interface AddCartItemInterface /** * Add the specified cart item. * - * @param CartItemInterface $cartItem The item. - * @return CartItemInterface Item. + * @param \Magento\Quote\Api\Data\CartItemInterface $cartItem The item. + * @return \Magento\Quote\Api\Data\CartItemInterface Item. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist. * @throws \Magento\Framework\Exception\CouldNotSaveException The specified item could not be saved to the cart. * @throws \Magento\Framework\Exception\InputException The specified item or cart is not valid. diff --git a/app/code/Magento/Quote/Api/UpdateCartItemInterface.php b/app/code/Magento/Quote/Api/UpdateCartItemInterface.php index 5409eb6251dd1..b797bd420b8fc 100644 --- a/app/code/Magento/Quote/Api/UpdateCartItemInterface.php +++ b/app/code/Magento/Quote/Api/UpdateCartItemInterface.php @@ -10,7 +10,7 @@ use Magento\Quote\Api\Data\CartItemInterface; /** - * Interface AddCartItemInterface + * Interface UpdateCartItemInterface * @api */ interface UpdateCartItemInterface @@ -18,8 +18,8 @@ interface UpdateCartItemInterface /** * Update the specified cart item. * - * @param CartItemInterface $cartItem The item. - * @return CartItemInterface Item. + * @param \Magento\Quote\Api\Data\CartItemInterface $cartItem The item. + * @return \Magento\Quote\Api\Data\CartItemInterface Item. * @throws \Magento\Framework\Exception\NoSuchEntityException The specified cart does not exist. * @throws \Magento\Framework\Exception\CouldNotSaveException The specified item could not be saved to the cart. * @throws \Magento\Framework\Exception\InputException The specified item or cart is not valid. From cb65f28b08c8ab292e8e86da8815cd63302cab3f Mon Sep 17 00:00:00 2001 From: engcom-Echo Date: Tue, 26 Jan 2021 13:59:53 +0200 Subject: [PATCH 6/6] MC-34298: Introduce separate POST and PUT API for carts/mine/items --- .../Magento/Bundle/Api/CartItemAddTest.php | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php index ef9bb3b8b473a..1e4620236392f 100644 --- a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/CartItemAddTest.php @@ -37,15 +37,16 @@ protected function setUp(): void } /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_items_saved.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php * @magentoApiDataFixture Magento/Bundle/_files/product.php */ public function testAddItem(): void { /** @var Product $product */ $product = $this->objectManager->create(Product::class)->load(3); + /** @var Quote $quote */ $quote = $this->objectManager->create(Quote::class)->load( - 'test_order_item_with_items', + 'test_order_1', 'reserved_order_id' ); @@ -57,13 +58,11 @@ public function testAddItem(): void 'bundle_option' => [$bundleOptionId => [$optionSelections]], 'bundle_option_qty' => [$bundleOptionId => 1], 'qty' => $itemQty, - 'original_qty' => $itemQty + 'original_qty' => $itemQty, ]; $productSku = $product->getSku(); $productId = $product->getId(); - /** @var Quote $quote */ - $cartId = $quote->getId(); $serviceInfo = [ @@ -89,12 +88,12 @@ public function testAddItem(): void [ "option_id" => (int)$bundleOptionId, "option_qty" => $itemQty, - "option_selections" => [(int)$optionSelections] - ] - ] - ] - ] - ] + "option_selections" => [(int)$optionSelections], + ], + ], + ], + ], + ], ]; $response = $this->_webApiCall($serviceInfo, $requestData); $this->assertTrue($quote->hasProductId($productId));