From f990b5885a02db2eacda700e3438ceb3012bb627 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Sun, 15 Dec 2024 10:50:14 +0530 Subject: [PATCH 1/8] Grouped product frontend quantity validation added and code refactor --- .../Block/Plugin/ProductView.php | 36 +++++------- .../Model/Product/QuantityValidator.php | 53 +++++++++++++++++ .../ViewModel/ValidateQuantity.php | 58 +++++++++++++++++++ .../catalog_product_view_type_grouped.xml | 14 +++-- .../templates/product/view/type/grouped.phtml | 17 +++--- .../wishlist_index_configure_type_grouped.xml | 10 +++- 6 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php create mode 100644 app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index c8245a53c147..eff32dd4c600 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -1,26 +1,26 @@ <?php /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. + * Copyright 2011 Adobe + * All Rights Reserved. */ namespace Magento\CatalogInventory\Block\Plugin; -use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\CatalogInventory\Model\Product\QuantityValidator; class ProductView { /** - * @var StockRegistryInterface + * @var QuantityValidator */ - private $stockRegistry; + private $productQuantityValidator; /** - * @param StockRegistryInterface $stockRegistry + * @param QuantityValidator $productQuantityValidator */ public function __construct( - StockRegistryInterface $stockRegistry + QuantityValidator $productQuantityValidator ) { - $this->stockRegistry = $stockRegistry; + $this->productQuantityValidator = $productQuantityValidator; } /** @@ -34,20 +34,12 @@ public function afterGetQuantityValidators( \Magento\Catalog\Block\Product\View $block, array $validators ) { - $stockItem = $this->stockRegistry->getStockItem( - $block->getProduct()->getId(), - $block->getProduct()->getStore()->getWebsiteId() + return array_merge( + $validators, + $this->productQuantityValidator->getData( + $block->getProduct()->getId(), + $block->getProduct()->getStore()->getWebsiteId() + ) ); - - $params = []; - if ($stockItem->getMaxSaleQty()) { - $params['maxAllowed'] = (float)$stockItem->getMaxSaleQty(); - } - if ($stockItem->getQtyIncrements() > 0) { - $params['qtyIncrements'] = (float)$stockItem->getQtyIncrements(); - } - $validators['validate-item-quantity'] = $params; - - return $validators; } } diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php new file mode 100644 index 000000000000..526d8d9d21a0 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright 2011 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +namespace Magento\CatalogInventory\Model\Product; + +use Magento\CatalogInventory\Api\StockRegistryInterface; + +class QuantityValidator +{ + /** + * @var StockRegistryInterface + */ + private $stockRegistry; + + /** + * @param StockRegistryInterface $stockRegistry + */ + public function __construct( + StockRegistryInterface $stockRegistry + ) { + $this->stockRegistry = $stockRegistry; + } + + /** + * To get quantity validators + * + * @param int $productId + * @param int $websiteId + * + * @return array + */ + public function getData($productId, $websiteId): array + { + $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); + + $params = []; + $validators = []; + $params['minAllowed'] = (float)$stockItem->getMinSaleQty(); + if ($stockItem->getMaxSaleQty()) { + $params['maxAllowed'] = (float)$stockItem->getMaxSaleQty(); + } + if ($stockItem->getQtyIncrements() > 0) { + $params['qtyIncrements'] = (float)$stockItem->getQtyIncrements(); + } + $validators['validate-item-quantity'] = $params; + + return $validators; + } +} diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php new file mode 100644 index 000000000000..df2a9d8bb394 --- /dev/null +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright 2011 Adobe + * All Rights Reserved. + */ +declare(strict_types=1); + +namespace Magento\GroupedProduct\ViewModel; + +use Magento\CatalogInventory\Model\Product\QuantityValidator; +use Magento\Framework\Serialize\Serializer\Json; +use Magento\Framework\View\Element\Block\ArgumentInterface; + +/** + * ViewModel for Grouped Products Block + */ +class ValidateQuantity implements ArgumentInterface +{ + /** + * @var Json + */ + private $serializer; + + /** + * @var QuantityValidator + */ + private $productQuantityValidator; + + /** + * @param Json $serializer + * @param QuantityValidator $productQuantityValidator + */ + public function __construct( + Json $serializer, + QuantityValidator $productQuantityValidator, + ) { + $this->serializer = $serializer; + $this->productQuantityValidator = $productQuantityValidator; + } + + /** + * To get the quantity validators + * + * @param int $productId + * @param int $websiteId + * + * @return string + */ + public function getQuantityValidators($productId, $websiteId): string + { + return $this->serializer->serialize( + array_merge( + ['validate-grouped-qty' => '#super-product-table'], + $this->productQuantityValidator->getData($productId, $websiteId) + ) + ); + } +} diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml index a774f384d947..7f99e022227a 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml @@ -1,15 +1,19 @@ <?xml version="1.0"?> <!-- -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ + /** + * Copyright 2011 Adobe + * All Rights Reserved. + */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <attribute name="class" value="page-product-grouped"/> <referenceContainer name="product.info.form.content"> - <block class="Magento\GroupedProduct\Block\Product\View\Type\Grouped" name="product.info.grouped" before="product.info.addtocart" template="Magento_GroupedProduct::product/view/type/grouped.phtml"/> + <block class="Magento\GroupedProduct\Block\Product\View\Type\Grouped" name="product.info.grouped" before="product.info.addtocart" template="Magento_GroupedProduct::product/view/type/grouped.phtml"> + <arguments> + <argument name="validateQuantityViewModel" xsi:type="object">Magento\GroupedProduct\ViewModel\ValidateQuantity</argument> + </arguments> + </block> <container name="product.info.grouped.extra" after="product.info.grouped" before="product.info.grouped" as="product_type_data_extra" label="Product Extra Info"/> </referenceContainer> <referenceContainer name="product.info.grouped.extra"> diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 996c61571563..7d5cab6dabba 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -1,7 +1,7 @@ <?php /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. + * Copyright 2011 Adobe + * All Rights Reserved. */ /** @@ -11,10 +11,13 @@ * @var $block \Magento\GroupedProduct\Block\Product\View\Type\Grouped */ ?> -<?php $block->setPreconfiguredValue(); ?> -<?php $_product = $block->getProduct(); ?> -<?php $_associatedProducts = $block->getAssociatedProducts(); ?> -<?php $_hasAssociatedProducts = count($_associatedProducts) > 0; ?> +<?php + $block->setPreconfiguredValue(); + $_product = $block->getProduct(); + $_associatedProducts = $block->getAssociatedProducts(); + $_hasAssociatedProducts = count($_associatedProducts) > 0; + $viewModel = $block->getData('validateQuantityViewModel'); +?> <div class="table-wrapper grouped"> <table class="table data grouped" @@ -52,7 +55,7 @@ value="<?= $block->escapeHtmlAttr($_item->getQty() * 1) ?>" title="<?= $block->escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" - data-validate="{'validate-grouped-qty':'#super-product-table'}" + data-validate="<?= $block->escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" data-errors-message-box="#validation-message-box"/> </div> <?php else: ?> diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml index 92bb55ebd0ee..0ac7e8819624 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml @@ -1,15 +1,19 @@ <?xml version="1.0"?> <!-- /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. + * Copyright 2011 Adobe + * All Rights Reserved. */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <attribute name="class" value="page-product-grouped"/> <referenceContainer name="product.info.form.content"> - <block class="Magento\GroupedProduct\Block\Product\View\Type\Grouped" name="product.info.grouped" before="product.info.addtocart" template="Magento_GroupedProduct::product/view/type/grouped.phtml"/> + <block class="Magento\GroupedProduct\Block\Product\View\Type\Grouped" name="product.info.grouped" before="product.info.addtocart" template="Magento_GroupedProduct::product/view/type/grouped.phtml"> + <arguments> + <argument name="validateQuantityViewModel" xsi:type="object">Magento\GroupedProduct\ViewModel\ValidateQuantity</argument> + </arguments> + </block> <container name="product.info.grouped.extra" after="product.info.grouped" before="product.info.grouped" as="product_type_data_extra" label="Product Extra Info"/> </referenceContainer> </body> From 94fadc842e83e1217082c3317829a7c49de3e299 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Fri, 20 Dec 2024 11:30:24 +0530 Subject: [PATCH 2/8] Ignore item qty validation if zero qty entered in grouped product --- .../view/frontend/templates/product/view/type/grouped.phtml | 1 + lib/web/mage/validation.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 7d5cab6dabba..71a5426600a0 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -56,6 +56,7 @@ title="<?= $block->escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" data-validate="<?= $block->escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" + data-no-validation-for-zero-qty="true" data-errors-message-box="#validation-message-box"/> </div> <?php else: ?> diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 72baf69740c9..6fdd221f2622 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1643,6 +1643,9 @@ define([ isQtyIncrementsValid = typeof params.qtyIncrements === 'undefined' || resolveModulo(qty, $.mage.parseNumber(params.qtyIncrements)) === 0.0; + if ($(element).data('no-validation-for-zero-qty') === true && qty === 0) { + return true; + } result = qty > 0; if (result === false) { From a1923771627e2cd1c40b5fd556ff633d8c8bfd4b Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Mon, 30 Dec 2024 11:23:52 +0530 Subject: [PATCH 3/8] Unit test & static test cases issues fixed --- .../Block/Plugin/ProductView.php | 2 +- .../Model/Product/QuantityValidator.php | 2 +- .../Unit/Block/Plugin/ProductViewTest.php | 23 ++++++++++--- .../ViewModel/ValidateQuantity.php | 2 +- .../catalog_product_view_type_grouped.xml | 2 +- .../templates/product/view/type/grouped.phtml | 32 +++++++++---------- .../wishlist_index_configure_type_grouped.xml | 2 +- 7 files changed, 40 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index eff32dd4c600..bcd9a00be937 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2011 Adobe + * Copyright 2015 Adobe * All Rights Reserved. */ namespace Magento\CatalogInventory\Block\Plugin; diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 526d8d9d21a0..16e6d8d98b70 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2011 Adobe + * Copyright 2024 Adobe * All Rights Reserved. */ declare(strict_types=1); diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php index ad01936633a5..48ba80121a82 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php @@ -1,7 +1,7 @@ <?php /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. + * Copyright 2015 Adobe + * All Rights Reserved. */ declare(strict_types=1); @@ -12,6 +12,7 @@ use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\CatalogInventory\Api\StockRegistryInterface; use Magento\CatalogInventory\Block\Plugin\ProductView; +use Magento\CatalogInventory\Model\Product\QuantityValidator; use Magento\CatalogInventory\Model\Stock\Item; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Store\Model\Store; @@ -35,6 +36,11 @@ class ProductViewTest extends TestCase */ protected $stockRegistry; + /** + * @var QuantityValidator|MockObject + */ + protected $productQuantityValidator; + protected function setUp(): void { $objectManager = new ObjectManager($this); @@ -47,10 +53,18 @@ protected function setUp(): void $this->stockRegistry = $this->getMockBuilder(StockRegistryInterface::class) ->getMock(); + + $this->productQuantityValidator = $objectManager->getObject( + QuantityValidator::class, + [ + 'stockRegistry' => $this->stockRegistry + ] + ); + $this->block = $objectManager->getObject( ProductView::class, [ - 'stockRegistry' => $this->stockRegistry + 'productQuantityValidator' => $this->productQuantityValidator ] ); } @@ -59,6 +73,7 @@ public function testAfterGetQuantityValidators() { $result = [ 'validate-item-quantity' => [ + 'minAllowed' => 1.0, 'maxAllowed' => 5.0, 'qtyIncrements' => 3.0 ] @@ -86,9 +101,9 @@ public function testAfterGetQuantityValidators() ->method('getStockItem') ->with('productId', 'websiteId') ->willReturn($this->stockItem); + $this->stockItem->expects($this->any())->method('getMinSaleQty')->willReturn(1); $this->stockItem->expects($this->any())->method('getMaxSaleQty')->willReturn(5); $this->stockItem->expects($this->any())->method('getQtyIncrements')->willReturn(3); - $this->assertEquals($result, $this->block->afterGetQuantityValidators($productViewBlock, $validators)); } } diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index df2a9d8bb394..c7367539770c 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -1,6 +1,6 @@ <?php /** - * Copyright 2011 Adobe + * Copyright 2024 Adobe * All Rights Reserved. */ declare(strict_types=1); diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml index 7f99e022227a..4a1f813484b3 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- /** - * Copyright 2011 Adobe + * Copyright 2015 Adobe * All Rights Reserved. */ --> diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 71a5426600a0..417d9012f98e 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -1,14 +1,14 @@ <?php /** - * Copyright 2011 Adobe + * Copyright 2015 Adobe * All Rights Reserved. */ /** * Grouped product data template * - * @var $block \Magento\Catalog\Block\Product\View\BaseImage * @var $block \Magento\GroupedProduct\Block\Product\View\Type\Grouped + * @var $escaper \Magento\Framework\Escaper */ ?> <?php @@ -23,12 +23,12 @@ <table class="table data grouped" id="super-product-table" data-mage-init='{ "Magento_GroupedProduct/js/product-ids-resolver": {} }'> - <caption class="table-caption"><?= $block->escapeHtml(__('Grouped product items')) ?></caption> + <caption class="table-caption"><?= $escaper->escapeHtml(__('Grouped product items')) ?></caption> <thead> <tr> - <th class="col item" scope="col"><?= $block->escapeHtml(__('Product Name')) ?></th> + <th class="col item" scope="col"><?= $escaper->escapeHtml(__('Product Name')) ?></th> <?php if ($_product->isSaleable()): ?> - <th class="col qty" scope="col"><?= $block->escapeHtml(__('Qty')) ?></th> + <th class="col qty" scope="col"><?= $escaper->escapeHtml(__('Qty')) ?></th> <?php endif; ?> </tr> </thead> @@ -37,8 +37,8 @@ <tbody> <?php foreach ($_associatedProducts as $_item): ?> <tr> - <td data-th="<?= $block->escapeHtml(__('Product Name')) ?>" class="col item"> - <strong class="product-item-name"><?= $block->escapeHtml($_item->getName()) ?></strong> + <td data-th="<?= $escaper->escapeHtml(__('Product Name')) ?>" class="col item"> + <strong class="product-item-name"><?= $escaper->escapeHtml($_item->getName()) ?></strong> <?php if ($block->getCanShowProductPrice($_product)): ?> <?php if ($block->getCanShowProductPrice($_item)): ?> <?= /* @noEscape */ $block->getProductPrice($_item) ?> @@ -46,22 +46,22 @@ <?php endif; ?> </td> <?php if ($_product->isSaleable()): ?> - <td data-th="<?= $block->escapeHtml(__('Qty')) ?>" class="col qty"> + <td data-th="<?= $escaper->escapeHtml(__('Qty')) ?>" class="col qty"> <?php if ($_item->isSaleable()): ?> <div class="control qty"> <input type="number" - name="super_group[<?= $block->escapeHtmlAttr($_item->getId()) ?>]" - data-selector="super_group[<?= $block->escapeHtmlAttr($_item->getId()) ?>]" - value="<?= $block->escapeHtmlAttr($_item->getQty() * 1) ?>" - title="<?= $block->escapeHtmlAttr(__('Qty')) ?>" + name="super_group[<?= $escaper->escapeHtmlAttr($_item->getId()) ?>]" + data-selector="super_group[<?= $escaper->escapeHtmlAttr($_item->getId()) ?>]" + value="<?= $escaper->escapeHtmlAttr($_item->getQty() * 1) ?>" + title="<?= $escaper->escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" - data-validate="<?= $block->escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" + data-validate="<?= $escaper->escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" data-no-validation-for-zero-qty="true" data-errors-message-box="#validation-message-box"/> </div> <?php else: ?> - <div class="stock unavailable" title="<?= $block->escapeHtmlAttr(__('Availability')) ?>"> - <span><?= $block->escapeHtml(__('Out of stock')) ?></span> + <div class="stock unavailable" title="<?= $escaper->escapeHtmlAttr(__('Availability')) ?>"> + <span><?= $escaper->escapeHtml(__('Out of stock')) ?></span> </div> <?php endif; ?> </td> @@ -89,7 +89,7 @@ <tr> <td class="unavailable" colspan="<?php if ($_product->isSaleable()): ?>4<?php else: ?>3<?php endif; ?>"> - <?= $block->escapeHtml(__('No options of this product are available.')) ?> + <?= $escaper->escapeHtml(__('No options of this product are available.')) ?> </td> </tr> </tbody> diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml index 0ac7e8819624..27d63bad57c0 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- /** - * Copyright 2011 Adobe + * Copyright 2015 Adobe * All Rights Reserved. */ --> From ceb85978679800380f66bde6bc08285c0b24201b Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Mon, 30 Dec 2024 18:27:43 +0530 Subject: [PATCH 4/8] Static test fixed --- .../Test/Unit/Block/Plugin/ProductViewTest.php | 1 - .../view/frontend/templates/product/view/type/grouped.phtml | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php index 48ba80121a82..94d08027362e 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php @@ -53,7 +53,6 @@ protected function setUp(): void $this->stockRegistry = $this->getMockBuilder(StockRegistryInterface::class) ->getMock(); - $this->productQuantityValidator = $objectManager->getObject( QuantityValidator::class, [ diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 417d9012f98e..3662149d7521 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -55,7 +55,10 @@ value="<?= $escaper->escapeHtmlAttr($_item->getQty() * 1) ?>" title="<?= $escaper->escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" - data-validate="<?= $escaper->escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" + data-validate="<?= $escaper->escapeHtmlAttr($viewModel->getQuantityValidators( + $_item->getId(), + $_item->getWebsiteId() + )) ?>" data-no-validation-for-zero-qty="true" data-errors-message-box="#validation-message-box"/> </div> From 3e0c5a76337e42bfdfd58f9777305ae48748e983 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Tue, 31 Dec 2024 15:02:33 +0530 Subject: [PATCH 5/8] Indent issue fixed --- lib/web/mage/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 6fdd221f2622..3f1df78dcfde 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1644,7 +1644,7 @@ define([ resolveModulo(qty, $.mage.parseNumber(params.qtyIncrements)) === 0.0; if ($(element).data('no-validation-for-zero-qty') === true && qty === 0) { - return true; + return true; } result = qty > 0; From 1ca6c6d8be284561ec999cde64cca934237f81c8 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Thu, 23 Jan 2025 21:52:04 +0530 Subject: [PATCH 6/8] Code review changes --- .../Block/Plugin/ProductView.php | 9 ++++++--- .../Model/Product/QuantityValidator.php | 18 ++++++----------- .../ViewModel/ValidateQuantity.php | 20 ++++--------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index bcd9a00be937..7f809e07b401 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -6,6 +6,7 @@ namespace Magento\CatalogInventory\Block\Plugin; use Magento\CatalogInventory\Model\Product\QuantityValidator; +use Magento\Framework\App\ObjectManager; class ProductView { @@ -15,12 +16,14 @@ class ProductView private $productQuantityValidator; /** - * @param QuantityValidator $productQuantityValidator + * @param QuantityValidator|null $productQuantityValidator */ public function __construct( - QuantityValidator $productQuantityValidator + QuantityValidator $productQuantityValidator = null ) { - $this->productQuantityValidator = $productQuantityValidator; + $this->productQuantityValidator = $productQuantityValidator ?: ObjectManager::getInstance()->get( + QuantityValidator::class + ); } /** diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 16e6d8d98b70..1ad6d938d73d 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -11,40 +11,34 @@ class QuantityValidator { - /** - * @var StockRegistryInterface - */ - private $stockRegistry; - /** * @param StockRegistryInterface $stockRegistry */ public function __construct( - StockRegistryInterface $stockRegistry + private readonly StockRegistryInterface $stockRegistry ) { - $this->stockRegistry = $stockRegistry; } /** * To get quantity validators * * @param int $productId - * @param int $websiteId + * @param int|null $websiteId * * @return array */ - public function getData($productId, $websiteId): array + public function getData(int $productId, int|null $websiteId): array { $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); $params = []; $validators = []; - $params['minAllowed'] = (float)$stockItem->getMinSaleQty(); + $params['minAllowed'] = $stockItem->getMinSaleQty(); if ($stockItem->getMaxSaleQty()) { - $params['maxAllowed'] = (float)$stockItem->getMaxSaleQty(); + $params['maxAllowed'] = $stockItem->getMaxSaleQty(); } if ($stockItem->getQtyIncrements() > 0) { - $params['qtyIncrements'] = (float)$stockItem->getQtyIncrements(); + $params['qtyIncrements'] = (float) $stockItem->getQtyIncrements(); } $validators['validate-item-quantity'] = $params; diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index c7367539770c..b8bf9bd6faad 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -16,37 +16,25 @@ */ class ValidateQuantity implements ArgumentInterface { - /** - * @var Json - */ - private $serializer; - - /** - * @var QuantityValidator - */ - private $productQuantityValidator; - /** * @param Json $serializer * @param QuantityValidator $productQuantityValidator */ public function __construct( - Json $serializer, - QuantityValidator $productQuantityValidator, + private readonly Json $serializer, + private readonly QuantityValidator $productQuantityValidator, ) { - $this->serializer = $serializer; - $this->productQuantityValidator = $productQuantityValidator; } /** * To get the quantity validators * * @param int $productId - * @param int $websiteId + * @param int|null $websiteId * * @return string */ - public function getQuantityValidators($productId, $websiteId): string + public function getQuantityValidators(int $productId, int|null $websiteId): string { return $this->serializer->serialize( array_merge( From baeb177a3bdf99a46a8744ee943f6146c291df9b Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Fri, 7 Mar 2025 15:49:59 +0530 Subject: [PATCH 7/8] Removed deprecated methods, get data using MSI and unit test added --- .../Block/Plugin/ProductView.php | 2 +- .../Model/Product/QuantityValidator.php | 68 ++++++++--- .../Unit/Block/Plugin/ProductViewTest.php | 108 ------------------ .../Model/Product/QuantityValidatorTest.php | 100 ++++++++++++++++ .../Magento/CatalogInventory/composer.json | 2 + .../Magento/CatalogInventory/etc/module.xml | 6 +- .../ViewModel/ValidateQuantity.php | 6 +- .../templates/product/view/type/grouped.phtml | 2 +- 8 files changed, 164 insertions(+), 130 deletions(-) delete mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php create mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index 7f809e07b401..38add312c2b4 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -40,7 +40,7 @@ public function afterGetQuantityValidators( return array_merge( $validators, $this->productQuantityValidator->getData( - $block->getProduct()->getId(), + $block->getProduct()->getSku(), $block->getProduct()->getStore()->getWebsiteId() ) ); diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 1ad6d938d73d..6c88da96e743 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -7,41 +7,79 @@ namespace Magento\CatalogInventory\Model\Product; -use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface; +use Magento\InventorySalesApi\Api\StockResolverInterface; +use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; +use Magento\Store\Model\StoreManagerInterface; class QuantityValidator { /** - * @param StockRegistryInterface $stockRegistry + * @param GetStockItemConfigurationInterface $getStockItemConfiguration + * @param StoreManagerInterface $storeManager + * @param StockResolverInterface $stockResolver */ public function __construct( - private readonly StockRegistryInterface $stockRegistry + private readonly GetStockItemConfigurationInterface $getStockItemConfiguration, + private readonly StoreManagerInterface $storeManager, + private readonly StockResolverInterface $stockResolver ) { } /** * To get quantity validators * - * @param int $productId + * @param string $sku * @param int|null $websiteId * * @return array */ - public function getData(int $productId, int|null $websiteId): array + public function getData(string $sku, int|null $websiteId): array { - $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); + try { + $stockItemConfig = $this->getStockItemConfiguration->execute( + $sku, + $this->getStockId($websiteId) + ); - $params = []; - $validators = []; - $params['minAllowed'] = $stockItem->getMinSaleQty(); - if ($stockItem->getMaxSaleQty()) { - $params['maxAllowed'] = $stockItem->getMaxSaleQty(); + $params = []; + $validators = []; + $params['minAllowed'] = $stockItemConfig->getMinSaleQty(); + + if ($stockItemConfig->getMaxSaleQty()) { + $params['maxAllowed'] = $stockItemConfig->getMaxSaleQty(); + } + if ($stockItemConfig->getQtyIncrements() > 0) { + $params['qtyIncrements'] = $stockItemConfig->getQtyIncrements(); + } + $validators['validate-item-quantity'] = $params; + + return $validators; + } catch (\Exception $e) { + return []; } - if ($stockItem->getQtyIncrements() > 0) { - $params['qtyIncrements'] = (float) $stockItem->getQtyIncrements(); + } + + /** + * Get Stock ID by Website ID + * + * @param int|null $websiteId + * @return int + * @throws LocalizedException + */ + private function getStockId(?int $websiteId): int + { + if ($websiteId === null) { + $websiteId = $this->storeManager->getWebsite()->getId(); } - $validators['validate-item-quantity'] = $params; - return $validators; + $websiteCode = $this->storeManager->getWebsite($websiteId)->getCode(); + $stock = $this->stockResolver->execute( + SalesChannelInterface::TYPE_WEBSITE, + $websiteCode + ); + + return (int) $stock->getStockId(); } } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php deleted file mode 100644 index 94d08027362e..000000000000 --- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php -/** - * Copyright 2015 Adobe - * All Rights Reserved. - */ -declare(strict_types=1); - -namespace Magento\CatalogInventory\Test\Unit\Block\Plugin; - -use Magento\Catalog\Block\Product\View; -use Magento\Catalog\Model\Product; -use Magento\CatalogInventory\Api\Data\StockItemInterface; -use Magento\CatalogInventory\Api\StockRegistryInterface; -use Magento\CatalogInventory\Block\Plugin\ProductView; -use Magento\CatalogInventory\Model\Product\QuantityValidator; -use Magento\CatalogInventory\Model\Stock\Item; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -use Magento\Store\Model\Store; -use PHPUnit\Framework\MockObject\MockObject; -use PHPUnit\Framework\TestCase; - -class ProductViewTest extends TestCase -{ - /** - * @var ProductView - */ - protected $block; - - /** - * @var StockItemInterface|MockObject - */ - protected $stockItem; - - /** - * @var StockRegistryInterface|MockObject - */ - protected $stockRegistry; - - /** - * @var QuantityValidator|MockObject - */ - protected $productQuantityValidator; - - protected function setUp(): void - { - $objectManager = new ObjectManager($this); - - $this->stockItem = $this->getMockBuilder(Item::class) - ->disableOriginalConstructor() - ->onlyMethods(['getMinSaleQty', 'getMaxSaleQty', 'getQtyIncrements']) - ->getMock(); - - $this->stockRegistry = $this->getMockBuilder(StockRegistryInterface::class) - ->getMock(); - - $this->productQuantityValidator = $objectManager->getObject( - QuantityValidator::class, - [ - 'stockRegistry' => $this->stockRegistry - ] - ); - - $this->block = $objectManager->getObject( - ProductView::class, - [ - 'productQuantityValidator' => $this->productQuantityValidator - ] - ); - } - - public function testAfterGetQuantityValidators() - { - $result = [ - 'validate-item-quantity' => [ - 'minAllowed' => 1.0, - 'maxAllowed' => 5.0, - 'qtyIncrements' => 3.0 - ] - ]; - $validators = []; - $productViewBlock = $this->getMockBuilder(View::class) - ->disableOriginalConstructor() - ->getMock(); - $productMock = $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->addMethods(['_wakeup']) - ->onlyMethods(['getId', 'getStore']) - ->getMock(); - $storeMock = $this->getMockBuilder(Store::class) - ->disableOriginalConstructor() - ->addMethods(['_wakeup']) - ->onlyMethods(['getWebsiteId']) - ->getMock(); - - $productViewBlock->expects($this->any())->method('getProduct')->willReturn($productMock); - $productMock->expects($this->once())->method('getId')->willReturn('productId'); - $productMock->expects($this->once())->method('getStore')->willReturn($storeMock); - $storeMock->expects($this->once())->method('getWebsiteId')->willReturn('websiteId'); - $this->stockRegistry->expects($this->once()) - ->method('getStockItem') - ->with('productId', 'websiteId') - ->willReturn($this->stockItem); - $this->stockItem->expects($this->any())->method('getMinSaleQty')->willReturn(1); - $this->stockItem->expects($this->any())->method('getMaxSaleQty')->willReturn(5); - $this->stockItem->expects($this->any())->method('getQtyIncrements')->willReturn(3); - $this->assertEquals($result, $this->block->afterGetQuantityValidators($productViewBlock, $validators)); - } -} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php new file mode 100644 index 000000000000..6589f442ed3c --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php @@ -0,0 +1,100 @@ +<?php +declare(strict_types=1); + +namespace Magento\CatalogInventory\Test\Unit\Model\Product; + +use Magento\CatalogInventory\Model\Product\QuantityValidator; +use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface; +use Magento\InventoryConfigurationApi\Api\Data\StockItemConfigurationInterface; +use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; +use Magento\InventoryApi\Api\Data\StockInterface; +use Magento\InventorySalesApi\Api\StockResolverInterface; +use Magento\Store\Api\Data\WebsiteInterface; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * @covers \Magento\CatalogInventory\Model\Product\QuantityValidator + */ +class QuantityValidatorTest extends TestCase +{ + private const WEBSITE_ID = 1; + private const WEBSITE_CODE = 'base'; + private const STOCK_ID = 1; + private const TEST_SKU = 'TEST-SKU'; + + /** + * @var QuantityValidator + */ + private $quantityValidator; + + /** + * @var GetStockItemConfigurationInterface|MockObject + */ + private $getStockItemConfiguration; + + /** + * @var StoreManagerInterface|MockObject + */ + private $storeManager; + + /** + * @var StockResolverInterface|MockObject + */ + private $stockResolver; + + protected function setUp(): void + { + $this->getStockItemConfiguration = $this->createMock(GetStockItemConfigurationInterface::class); + $this->storeManager = $this->createMock(StoreManagerInterface::class); + $this->stockResolver = $this->createMock(StockResolverInterface::class); + + $this->quantityValidator = new QuantityValidator( + $this->getStockItemConfiguration, + $this->storeManager, + $this->stockResolver + ); + } + + public function testGetDataWithValidators(): void + { + $website = $this->createMock(WebsiteInterface::class); + $website->method('getCode')->willReturn(self::WEBSITE_CODE); + + $stock = $this->createMock(StockInterface::class); + $stock->method('getStockId')->willReturn(self::STOCK_ID); + + $stockItemConfiguration = $this->createMock(StockItemConfigurationInterface::class); + $stockItemConfiguration->method('getMinSaleQty')->willReturn(2.0); + $stockItemConfiguration->method('getMaxSaleQty')->willReturn(10.0); + $stockItemConfiguration->method('getQtyIncrements')->willReturn(2.0); + + // Set expectations + $this->storeManager->expects($this->once()) + ->method('getWebsite') + ->with(self::WEBSITE_ID) + ->willReturn($website); + + $this->stockResolver->expects($this->once()) + ->method('execute') + ->with(SalesChannelInterface::TYPE_WEBSITE, self::WEBSITE_CODE) + ->willReturn($stock); + + $this->getStockItemConfiguration->expects($this->once()) + ->method('execute') + ->with(self::TEST_SKU, self::STOCK_ID) + ->willReturn($stockItemConfiguration); + + $expected = [ + 'validate-item-quantity' => [ + 'minAllowed' => 2, + 'maxAllowed' => 10, + 'qtyIncrements' => 2.0 + ] + ]; + + $result = $this->quantityValidator->getData(self::TEST_SKU, self::WEBSITE_ID); + $this->assertEquals($expected, $result); + } +} diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index d78c97d97eed..c452c042d5f4 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -8,6 +8,8 @@ "php": "~8.2.0||~8.3.0||~8.4.0", "magento/framework": "*", "magento/module-catalog": "*", + "magento/module-inventory-configuration-api": "*", + "magento/module-inventory-sales-api": "*", "magento/module-config": "*", "magento/module-customer": "*", "magento/module-eav": "*", diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml index d643c5015130..775d4f94139e 100644 --- a/app/code/Magento/CatalogInventory/etc/module.xml +++ b/app/code/Magento/CatalogInventory/etc/module.xml @@ -1,14 +1,16 @@ <?xml version="1.0"?> <!-- /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. + * Copyright 2011 Adobe + * All Rights Reserved. */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Magento_CatalogInventory" > <sequence> <module name="Magento_Catalog"/> + <module name="Magento_InventoryConfigurationApi"/> + <module name="Magento_InventorySalesApi"/> </sequence> </module> </config> diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index b8bf9bd6faad..d987c89e0ad9 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -29,17 +29,17 @@ public function __construct( /** * To get the quantity validators * - * @param int $productId + * @param string $sku * @param int|null $websiteId * * @return string */ - public function getQuantityValidators(int $productId, int|null $websiteId): string + public function getQuantityValidators(string $sku, int|null $websiteId): string { return $this->serializer->serialize( array_merge( ['validate-grouped-qty' => '#super-product-table'], - $this->productQuantityValidator->getData($productId, $websiteId) + $this->productQuantityValidator->getData($sku, $websiteId) ) ); } diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 3662149d7521..05b973bd94b8 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -56,7 +56,7 @@ title="<?= $escaper->escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" data-validate="<?= $escaper->escapeHtmlAttr($viewModel->getQuantityValidators( - $_item->getId(), + $_item->getSku(), $_item->getWebsiteId() )) ?>" data-no-validation-for-zero-qty="true" From 9a46f52f04d5a88673f4c4463abcb9b8c83b8b25 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen <mdasar2595@gmail.com> Date: Mon, 10 Mar 2025 14:07:02 +0530 Subject: [PATCH 8/8] Static test case fix --- .../Test/Unit/Model/Product/QuantityValidatorTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php index 6589f442ed3c..483d610db972 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php @@ -1,4 +1,8 @@ <?php +/** + * Copyright 2025 Adobe + * All Rights Reserved. + */ declare(strict_types=1); namespace Magento\CatalogInventory\Test\Unit\Model\Product;