Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 302437a

Browse files
authored
Merge pull request #3496 from magento-mpi/fix-95898
[MPI]-fix-95898
2 parents 3dd49b7 + 2af88f1 commit 302437a

File tree

6 files changed

+280
-21
lines changed

6 files changed

+280
-21
lines changed

app/code/Magento/Checkout/Controller/Sidebar/UpdateItemQty.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ public function __construct(
5050
}
5151

5252
/**
53-
* @return $this
53+
* @inheritdoc
5454
*/
5555
public function execute()
5656
{
5757
$itemId = (int)$this->getRequest()->getParam('item_id');
58-
$itemQty = (int)$this->getRequest()->getParam('item_qty');
58+
$itemQty = $this->getRequest()->getParam('item_qty');
5959

6060
try {
6161
$this->sidebar->checkQuoteItem($itemId);

app/code/Magento/Checkout/Test/Unit/Controller/Sidebar/UpdateItemQtyTest.php

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,46 @@
55
*/
66
namespace Magento\Checkout\Test\Unit\Controller\Sidebar;
77

8+
use Magento\Checkout\Controller\Sidebar\UpdateItemQty;
9+
use Magento\Checkout\Model\Sidebar;
10+
use Magento\Framework\App\RequestInterface;
11+
use Magento\Framework\App\ResponseInterface;
812
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Json\Helper\Data;
914
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
15+
use Psr\Log\LoggerInterface;
1016

1117
class UpdateItemQtyTest extends \PHPUnit\Framework\TestCase
1218
{
13-
/** @var \Magento\Checkout\Controller\Sidebar\UpdateItemQty */
14-
protected $updateItemQty;
19+
/** @var UpdateItemQty */
20+
private $updateItemQty;
1521

1622
/** @var ObjectManagerHelper */
17-
protected $objectManagerHelper;
23+
private $objectManagerHelper;
1824

19-
/** @var \Magento\Checkout\Model\Sidebar|\PHPUnit_Framework_MockObject_MockObject */
20-
protected $sidebarMock;
25+
/** @var Sidebar|\PHPUnit_Framework_MockObject_MockObject */
26+
private $sidebarMock;
2127

22-
/** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
23-
protected $loggerMock;
28+
/** @var LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */
29+
private $loggerMock;
2430

25-
/** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
26-
protected $jsonHelperMock;
31+
/** @var Data|\PHPUnit_Framework_MockObject_MockObject */
32+
private $jsonHelperMock;
2733

28-
/** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
29-
protected $requestMock;
34+
/** @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
35+
private $requestMock;
3036

31-
/** @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */
32-
protected $responseMock;
37+
/** @var ResponseInterface|\PHPUnit_Framework_MockObject_MockObject */
38+
private $responseMock;
3339

3440
protected function setUp()
3541
{
36-
$this->sidebarMock = $this->createMock(\Magento\Checkout\Model\Sidebar::class);
37-
$this->loggerMock = $this->createMock(\Psr\Log\LoggerInterface::class);
38-
$this->jsonHelperMock = $this->createMock(\Magento\Framework\Json\Helper\Data::class);
39-
$this->requestMock = $this->createMock(\Magento\Framework\App\RequestInterface::class);
42+
$this->sidebarMock = $this->createMock(Sidebar::class);
43+
$this->loggerMock = $this->createMock(LoggerInterface::class);
44+
$this->jsonHelperMock = $this->createMock(Data::class);
45+
$this->requestMock = $this->createMock(RequestInterface::class);
4046
$this->responseMock = $this->getMockForAbstractClass(
41-
\Magento\Framework\App\ResponseInterface::class,
47+
ResponseInterface::class,
4248
[],
4349
'',
4450
false,
@@ -49,7 +55,7 @@ protected function setUp()
4955

5056
$this->objectManagerHelper = new ObjectManagerHelper($this);
5157
$this->updateItemQty = $this->objectManagerHelper->getObject(
52-
\Magento\Checkout\Controller\Sidebar\UpdateItemQty::class,
58+
UpdateItemQty::class,
5359
[
5460
'sidebar' => $this->sidebarMock,
5561
'logger' => $this->loggerMock,
@@ -60,6 +66,9 @@ protected function setUp()
6066
);
6167
}
6268

69+
/**
70+
* Tests execute action.
71+
*/
6372
public function testExecute()
6473
{
6574
$this->requestMock->expects($this->at(0))
@@ -113,6 +122,9 @@ public function testExecute()
113122
$this->assertEquals('json represented', $this->updateItemQty->execute());
114123
}
115124

125+
/**
126+
* Tests with localized exception.
127+
*/
116128
public function testExecuteWithLocalizedException()
117129
{
118130
$this->requestMock->expects($this->at(0))
@@ -157,6 +169,9 @@ public function testExecuteWithLocalizedException()
157169
$this->assertEquals('json represented', $this->updateItemQty->execute());
158170
}
159171

172+
/**
173+
* Tests with exception.
174+
*/
160175
public function testExecuteWithException()
161176
{
162177
$this->requestMock->expects($this->at(0))
@@ -207,4 +222,31 @@ public function testExecuteWithException()
207222

208223
$this->assertEquals('json represented', $this->updateItemQty->execute());
209224
}
225+
226+
/**
227+
* Tests execute with float item quantity.
228+
*/
229+
public function testExecuteWithFloatItemQty()
230+
{
231+
$itemId = '1';
232+
$floatItemQty = '2.2';
233+
234+
$this->requestMock->expects($this->at(0))
235+
->method('getParam')
236+
->with('item_id', null)
237+
->willReturn($itemId);
238+
$this->requestMock->expects($this->at(1))
239+
->method('getParam')
240+
->with('item_qty', null)
241+
->willReturn($floatItemQty);
242+
243+
$this->sidebarMock->expects($this->once())
244+
->method('checkQuoteItem')
245+
->with($itemId);
246+
$this->sidebarMock->expects($this->once())
247+
->method('updateQuoteItem')
248+
->with($itemId, $floatItemQty);
249+
250+
$this->updateItemQty->execute();
251+
}
210252
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Catalog\Api\ProductRepositoryInterface;
8+
use Magento\Catalog\Model\Product;
9+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
10+
use Magento\Catalog\Model\Product\Type;
11+
use Magento\Catalog\Model\Product\Visibility;
12+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
13+
use Magento\TestFramework\Helper\Bootstrap;
14+
use Magento\TestFramework\ObjectManager;
15+
16+
/** @var ObjectManager $objectManager */
17+
$objectManager = Bootstrap::getObjectManager();
18+
19+
/** @var Product $product */
20+
$product = $objectManager->create(Product::class);
21+
$product->isObjectNew(true);
22+
$product->setTypeId(Type::TYPE_SIMPLE)
23+
->setAttributeSetId(4)
24+
->setWebsiteIds([1])
25+
->setName('Simple Product Decimal Qty')
26+
->setSku('simple_with_decimal_qty')
27+
->setPrice(10)
28+
->setWeight(1)
29+
->setVisibility(Visibility::VISIBILITY_BOTH)
30+
->setStatus(Status::STATUS_ENABLED);
31+
32+
/** @var StockItemInterface $stockItem */
33+
$stockItem = $objectManager->create(StockItemInterface::class);
34+
$stockItem->setIsInStock(true)
35+
->setQty(10000)
36+
->setIsQtyDecimal(true)
37+
->setUseConfigMinSaleQty(false)
38+
->setMinSaleQty(1.1)
39+
->setUseConfigEnableQtyInc(false)
40+
->setEnableQtyIncrements(true)
41+
->setUseConfigQtyIncrements(false)
42+
->setQtyIncrements(1.1);
43+
44+
$extensionAttributes = $product->getExtensionAttributes();
45+
$extensionAttributes->setStockItem($stockItem);
46+
47+
/** @var ProductRepositoryInterface $productRepository */
48+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
49+
$product = $productRepository->save($product);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Catalog\Api\ProductRepositoryInterface;
8+
use Magento\TestFramework\Helper\Bootstrap;
9+
use Magento\TestFramework\ObjectManager;
10+
11+
/** @var ObjectManager $objectManager */
12+
$objectManager = Bootstrap::getObjectManager();
13+
14+
/** @var ProductRepositoryInterface $productRepository */
15+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
16+
$productRepository->deleteById('simple_with_decimal_qty');
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Checkout\Controller\Sidebar;
9+
10+
use Magento\Checkout\Model\Session;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\Framework\Api\SearchCriteriaBuilder;
13+
use Magento\Framework\Serialize\Serializer\Json;
14+
use Magento\Quote\Api\CartRepositoryInterface;
15+
use Magento\Quote\Model\Quote;
16+
17+
/**
18+
* Tests update item quantity controller.
19+
*/
20+
class UpdateItemQtyTest extends \Magento\TestFramework\TestCase\AbstractController
21+
{
22+
/**
23+
* @var Json
24+
*/
25+
private $json;
26+
27+
/**
28+
* @var Session
29+
*/
30+
private $session;
31+
32+
/**
33+
* @var ProductRepositoryInterface
34+
*/
35+
private $productRepository;
36+
37+
protected function setUp()
38+
{
39+
parent::setUp();
40+
41+
$this->json = $this->_objectManager->create(Json::class);
42+
$this->session = $this->_objectManager->create(Session::class);
43+
$this->productRepository = $this->_objectManager->create(ProductRepositoryInterface::class);
44+
}
45+
46+
/**
47+
* Tests of cart validation when contains product with decimal quantity.
48+
*
49+
* @param string $requestQuantity
50+
* @param array $expectedResponse
51+
*
52+
* @magentoAppArea frontend
53+
* @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_decimal_qty.php
54+
* @dataProvider executeWithDecimalQtyDataProvider
55+
* @throws \Magento\Framework\Exception\NoSuchEntityException
56+
*/
57+
public function testExecuteWithDecimalQty(string $requestQuantity, array $expectedResponse)
58+
{
59+
$product = $this->productRepository->get('simple_with_decimal_qty');
60+
$quote = $this->getQuote('decimal_quote_id');
61+
$quoteItem = $quote->getItemByProduct($product);
62+
$this->session->setQuoteId($quote->getId());
63+
64+
$this->assertNotNull($quoteItem, 'Cannot get quote item for simple product');
65+
66+
$request= [
67+
'item_id' => $quoteItem->getId(),
68+
'item_qty' => $requestQuantity
69+
];
70+
71+
$this->getRequest()->setPostValue($request);
72+
$this->dispatch('checkout/sidebar/updateItemQty');
73+
$response = $this->getResponse()->getBody();
74+
75+
$this->assertEquals($this->json->unserialize($response), $expectedResponse);
76+
}
77+
78+
/**
79+
* Variations of request data.
80+
* @returns array
81+
*/
82+
public function executeWithDecimalQtyDataProvider(): array
83+
{
84+
return [
85+
[
86+
'requestQuantity' => '2.2',
87+
'response' => [
88+
'success' => true,
89+
]
90+
],
91+
[
92+
'requestQuantity' => '2',
93+
'response' => [
94+
'success' => false,
95+
'error_message' => 'You can buy this product only in quantities of 1.1 at a time.']
96+
],
97+
];
98+
}
99+
100+
/**
101+
* Retrieves quote by reserved order id.
102+
*
103+
* @param string $reservedOrderId
104+
* @return Quote
105+
*/
106+
private function getQuote(string $reservedOrderId): Quote
107+
{
108+
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
109+
$searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class);
110+
$searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId)
111+
->create();
112+
113+
/** @var CartRepositoryInterface $quoteRepository */
114+
$quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class);
115+
$items = $quoteRepository->getList($searchCriteria)->getItems();
116+
117+
return array_pop($items);
118+
}
119+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Catalog\Api\ProductRepositoryInterface;
9+
use Magento\Quote\Api\CartRepositoryInterface;
10+
use Magento\Quote\Model\Quote;
11+
use Magento\TestFramework\Helper\Bootstrap;
12+
13+
require __DIR__ . '/../../../Magento/CatalogInventory/_files/simple_product_decimal_qty.php';
14+
15+
/** @var ProductRepositoryInterface $productRepository */
16+
$productRepository = Bootstrap::getObjectManager()
17+
->create(ProductRepositoryInterface::class);
18+
/** @var $product \Magento\Catalog\Model\Product */
19+
$product = $productRepository->get('simple_with_decimal_qty');
20+
21+
/** @var Quote $quote */
22+
$quote = Bootstrap::getObjectManager()->create(Quote::class);
23+
$quote->setReservedOrderId('decimal_quote_id');
24+
$item = $objectManager->create(\Magento\Quote\Model\Quote\Item::class);
25+
$item->setProduct($product)
26+
->setPrice($product->getPrice())
27+
->setQty(1.1);
28+
$quote->addItem($item);
29+
30+
31+
/** @var CartRepositoryInterface $quoteRepository */
32+
$quoteRepository = $objectManager->get(CartRepositoryInterface::class);
33+
$quoteRepository->save($quote);

0 commit comments

Comments
 (0)