Skip to content

Commit 0c0e319

Browse files
committed
Merge branch 'ACP2E-2174' of https://github.com/magento-l3/magento2ce into PR2-L3-09132023
2 parents 18a269e + dc7a7f8 commit 0c0e319

File tree

3 files changed

+163
-3
lines changed

3 files changed

+163
-3
lines changed

app/code/Magento/Checkout/Controller/Cart/UpdatePost.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ protected function _updateShoppingCart()
8383
$this->cart->updateItems($cartData)->save();
8484
}
8585
} catch (\Magento\Framework\Exception\LocalizedException $e) {
86+
$this->cart->save();
8687
$this->messageManager->addErrorMessage(
8788
$this->_objectManager->get(\Magento\Framework\Escaper::class)->escapeHtml($e->getMessage())
8889
);

app/code/Magento/Checkout/Model/Cart.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
2020
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2121
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
22+
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
2223
* @deprecated 100.1.0 Use \Magento\Quote\Model\Quote instead
2324
* @see \Magento\Quote\Api\Data\CartInterface
2425
* @since 100.0.2
@@ -522,6 +523,7 @@ public function updateItems($data)
522523
);
523524

524525
$qtyRecalculatedFlag = false;
526+
$itemErrors = [];
525527
foreach ($data as $itemId => $itemInfo) {
526528
$item = $this->getQuote()->getItemById($itemId);
527529
if (!$item) {
@@ -540,7 +542,7 @@ public function updateItems($data)
540542
$item->setQty($qty);
541543

542544
if ($item->getHasError()) {
543-
throw new \Magento\Framework\Exception\LocalizedException(__($item->getMessage()));
545+
$itemErrors[$item->getId()] = __($item->getMessage());
544546
}
545547

546548
if (isset($itemInfo['before_suggest_qty']) && $itemInfo['before_suggest_qty'] != $qty) {
@@ -564,6 +566,10 @@ public function updateItems($data)
564566
['cart' => $this, 'info' => $infoDataObject]
565567
);
566568

569+
if (count($itemErrors)) {
570+
throw new \Magento\Framework\Exception\LocalizedException(current($itemErrors));
571+
}
572+
567573
return $this;
568574
}
569575

dev/tests/integration/testsuite/Magento/Checkout/Controller/CartTest.php

Lines changed: 155 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@
1010
namespace Magento\Checkout\Controller;
1111

1212
use Magento\Catalog\Api\ProductRepositoryInterface;
13-
use Magento\Checkout\Model\Session;
13+
use Magento\Catalog\Model\Product;
14+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
15+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
1416
use Magento\Checkout\Model\Session as CheckoutSession;
1517
use Magento\Customer\Model\ResourceModel\CustomerRepository;
1618
use Magento\Framework\Data\Form\FormKey;
1719
use Magento\Framework\Api\SearchCriteriaBuilder;
20+
use Magento\Framework\Exception\LocalizedException;
21+
use Magento\Framework\Exception\NoSuchEntityException;
22+
use Magento\Quote\Api\Data\CartInterface;
23+
use Magento\Quote\Api\Data\CartItemInterface;
1824
use Magento\Quote\Model\Quote;
1925
use Magento\Quote\Api\CartRepositoryInterface;
26+
use Magento\Quote\Model\QuoteRepository;
27+
use Magento\Quote\Test\Fixture\AddProductToCart;
28+
use Magento\Quote\Test\Fixture\GuestCart;
29+
use Magento\TestFramework\Fixture\DataFixture;
30+
use Magento\TestFramework\Fixture\DataFixtureStorage;
31+
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
2032
use Magento\TestFramework\Helper\Bootstrap;
2133
use Magento\TestFramework\Request;
2234
use Magento\Customer\Model\Session as CustomerSession;
@@ -33,6 +45,16 @@ class CartTest extends \Magento\TestFramework\TestCase\AbstractController
3345
/** @var CheckoutSession */
3446
private $checkoutSession;
3547

48+
/**
49+
* @var ProductRepositoryInterface
50+
*/
51+
private $productRepository;
52+
53+
/**
54+
* @var DataFixtureStorage
55+
*/
56+
private $fixtures;
57+
3658
/**
3759
* @inheritdoc
3860
*/
@@ -41,6 +63,8 @@ protected function setUp(): void
4163
parent::setUp();
4264
$this->checkoutSession = $this->_objectManager->get(CheckoutSession::class);
4365
$this->_objectManager->addSharedInstance($this->checkoutSession, CheckoutSession::class);
66+
$this->productRepository = $this->_objectManager->create(ProductRepositoryInterface::class);
67+
$this->fixtures = DataFixtureStorageManager::getStorage();
4468
}
4569

4670
/**
@@ -370,7 +394,7 @@ public function testReorderItems(bool $loggedIn, string $request)
370394
$customerSession = $this->_objectManager->get(CustomerSession::class);
371395
$customerSession->logout();
372396

373-
$checkoutSession = Bootstrap::getObjectManager()->get(Session::class);
397+
$checkoutSession = Bootstrap::getObjectManager()->get(CheckoutSession::class);
374398
$expected = [];
375399
if ($loggedIn && $request == Request::METHOD_POST) {
376400
$customer = $this->_objectManager->create(CustomerRepository::class)->get('customer2@example.com');
@@ -447,4 +471,133 @@ private function prepareRequest(string $method)
447471
break;
448472
}
449473
}
474+
475+
/**
476+
* @throws NoSuchEntityException
477+
* @throws LocalizedException
478+
*/
479+
#[
480+
DataFixture(ProductFixture::class, ['sku' => 's1', 'stock_item' => ['is_in_stock' => true]], 'p1'),
481+
DataFixture(ProductFixture::class, ['sku' => 's2','stock_item' => ['is_in_stock' => true]], 'p2'),
482+
DataFixture(GuestCart::class, as: 'cart'),
483+
DataFixture(
484+
AddProductToCart::class,
485+
['cart_id' => '$cart.id$', 'product_id' => '$p1.id$', 'qty' => 1],
486+
'item1'
487+
),
488+
DataFixture(
489+
AddProductToCart::class,
490+
['cart_id' => '$cart.id$', 'product_id' => '$p2.id$', 'qty' => 1],
491+
'item2'
492+
)
493+
]
494+
public function testUpdatePostActionWithMultipleProducts()
495+
{
496+
$cartId = (int)$this->fixtures->get('cart')->getId();
497+
if (!$cartId) {
498+
$this->fail('quote fixture failed');
499+
}
500+
/** @var QuoteRepository $quoteRepository */
501+
$quoteRepository = Bootstrap::getObjectManager()->get(QuoteRepository::class);
502+
$quote = $quoteRepository->get($cartId);
503+
504+
$checkoutSession = Bootstrap::getObjectManager()->get(CheckoutSession::class);
505+
$checkoutSession->setQuoteId($quote->getId());
506+
507+
/** @var \Magento\Quote\Model\Quote\Item $item1 */
508+
$item1 = $this->fixtures->get('item1');
509+
/** @var \Magento\Quote\Model\Quote\Item $item2 */
510+
$item2 = $this->fixtures->get('item2');
511+
512+
$p1 = $this->fixtures->get('p1');
513+
/** @var $p1 Product */
514+
$product1 = $this->productRepository->get($p1->getSku(), true);
515+
$stockItem = $product1->getExtensionAttributes()->getStockItem();
516+
$stockItem->setQty(0);
517+
$stockItem->setIsInStock(false);
518+
$stockItemRepository = Bootstrap::getObjectManager()->get(StockItemRepositoryInterface::class);
519+
$stockItemRepository->save($stockItem);
520+
521+
$originalQuantity = 1;
522+
$updatedQuantity = 2;
523+
524+
$this->assertEquals(
525+
$originalQuantity + $originalQuantity,
526+
$quote->getItemsQty(),
527+
"Precondition failed: quote totals does not match."
528+
);
529+
530+
$response = $this->updatePostRequest($quote, $item1, $item2, $updatedQuantity, $updatedQuantity, true);
531+
532+
$this->assertStringContainsString(
533+
'"itemId":'.$item1->getId().'}]',
534+
$response['error_message']
535+
);
536+
537+
$response = $this->updatePostRequest($quote, $item1, $item2, $originalQuantity, $updatedQuantity, false);
538+
539+
$this->assertStringContainsString(
540+
'"itemId":'.$item1->getId().'}]',
541+
$response['error_message']
542+
);
543+
$this->assertEquals(
544+
$originalQuantity + $updatedQuantity,
545+
$quote->getItemsQty(),
546+
"Precondition failed: quote totals does not match."
547+
);
548+
549+
$response = $this->updatePostRequest($quote, $item1, $item2, $updatedQuantity, $updatedQuantity, false);
550+
551+
$this->assertStringContainsString(
552+
'"itemId":'.$item1->getId().'}]',
553+
$response['error_message']
554+
);
555+
$this->assertEquals(
556+
$originalQuantity + $updatedQuantity,
557+
$quote->getItemsQty(),
558+
"Precondition failed: quote totals does not match."
559+
);
560+
}
561+
562+
/**
563+
* @param CartInterface $quote
564+
* @param CartItemInterface $item1
565+
* @param CartItemInterface $item2
566+
* @param float $qty1
567+
* @param float $qty2
568+
* @param bool $updateQty
569+
* @return mixed
570+
* @throws LocalizedException
571+
*/
572+
private function updatePostRequest(
573+
CartInterface $quote,
574+
CartItemInterface $item1,
575+
CartItemInterface $item2,
576+
float $qty1,
577+
float $qty2,
578+
bool $updateQty = true
579+
): array {
580+
/** @var FormKey $formKey */
581+
$formKey = Bootstrap::getObjectManager()->get(FormKey::class);
582+
583+
$request = [
584+
'cart' => [
585+
$item1->getId() => ['qty' => $qty1],
586+
$item2->getId() => ['qty' => $qty2]
587+
],
588+
'update_cart_action' => 'update_qty',
589+
'form_key' => $formKey->getFormKey(),
590+
];
591+
$this->getRequest()->setMethod(HttpRequest::METHOD_POST);
592+
$this->getRequest()->setPostValue($request);
593+
if ($updateQty) {
594+
$this->dispatch('checkout/cart/updateItemQty');
595+
} else {
596+
$this->dispatch('checkout/cart/updatePost');
597+
$quote->collectTotals();
598+
}
599+
$response = $this->getResponse()->getBody();
600+
$response = json_decode($response, true);
601+
return $response;
602+
}
450603
}

0 commit comments

Comments
 (0)