From 90b6803aab559cd0c345ab42d19bb712e4df8011 Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Fri, 22 Jun 2018 17:48:44 +0300 Subject: [PATCH 01/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Use configurable product`s children for shopping cart rules validation for cases when attribute exists for children only (E.g. special_price) --- .../Model/Rule/Condition/Product.php | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index 499e35db9dfd6..35ace4b6b089e 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -5,10 +5,14 @@ */ namespace Magento\SalesRule\Model\Rule\Condition; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; + /** * Product rule condition data model * * @author Magento Core Team + * + * @method string getAttribute() */ class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct { @@ -26,20 +30,47 @@ protected function _addSpecialAttributes(array &$attributes) $attributes['quote_item_row_total'] = __('Row total in cart'); } + /** + * @param \Magento\Framework\Model\AbstractModel $model + * + * @return \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + protected function getProductToValidate(\Magento\Framework\Model\AbstractModel $model) + { + /** @var \Magento\Catalog\Model\Product $product */ + $product = $model->getProduct(); + if (!$product instanceof \Magento\Catalog\Model\Product) { + $product = $this->productRepository->getById($model->getProductId()); + } + + $attrCode = $this->getAttribute(); + + /* Check for attributes which are not available for configurable products */ + if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) { + /** @var \Magento\Catalog\Api\Data\ProductInterface $childProduct */ + $childProduct = current($model->getChildren())->getProduct(); + if ($childProduct->hasData($attrCode)) { + $product = $childProduct; + } + } + + return $product; + } + /** * Validate Product Rule Condition * * @param \Magento\Framework\Model\AbstractModel $model + * * @return bool + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function validate(\Magento\Framework\Model\AbstractModel $model) { //@todo reimplement this method when is fixed MAGETWO-5713 /** @var \Magento\Catalog\Model\Product $product */ - $product = $model->getProduct(); - if (!$product instanceof \Magento\Catalog\Model\Product) { - $product = $this->productRepository->getById($model->getProductId()); - } + $product = $this->getProductToValidate($model); $product->setQuoteItemQty( $model->getQty() @@ -49,9 +80,8 @@ public function validate(\Magento\Framework\Model\AbstractModel $model) $model->getBaseRowTotal() ); - $attrCode = $this->getAttribute(); - if ('category_ids' == $attrCode) { + if ('category_ids' == $this->getAttribute()) { return $this->validateAttribute($this->_getAvailableInCategories($product->getId())); } From 2717cb1729b6f1b61040f3eb1582eb1d60622893 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Mon, 25 Jun 2018 22:19:16 +0200 Subject: [PATCH 02/34] Removed empty line due to failing static test --- app/code/Magento/SalesRule/Model/Rule/Condition/Product.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index 35ace4b6b089e..8a9e6f7f2b66c 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -80,7 +80,6 @@ public function validate(\Magento\Framework\Model\AbstractModel $model) $model->getBaseRowTotal() ); - if ('category_ids' == $this->getAttribute()) { return $this->validateAttribute($this->_getAvailableInCategories($product->getId())); } From d2a0de83c0f73dd850925b4a70ab2e5cf233d74b Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Tue, 26 Jun 2018 16:25:41 +0200 Subject: [PATCH 03/34] Removed dependency to configurable product --- app/code/Magento/SalesRule/Model/Rule/Condition/Product.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index 8a9e6f7f2b66c..e17cc9b16535e 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -5,8 +5,6 @@ */ namespace Magento\SalesRule\Model\Rule\Condition; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; - /** * Product rule condition data model * @@ -47,7 +45,7 @@ protected function getProductToValidate(\Magento\Framework\Model\AbstractModel $ $attrCode = $this->getAttribute(); /* Check for attributes which are not available for configurable products */ - if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) { + if ($product->isComposite() && !$product->hasData($attrCode)) { /** @var \Magento\Catalog\Api\Data\ProductInterface $childProduct */ $childProduct = current($model->getChildren())->getProduct(); if ($childProduct->hasData($attrCode)) { From fae98c01e29ea9ca47eca00cf2081ede1f729ccb Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Wed, 4 Jul 2018 22:55:35 +0300 Subject: [PATCH 04/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Revert "Removed dependency to configurable product" This reverts commit d2a0de83c0f73dd850925b4a70ab2e5cf233d74b. --- app/code/Magento/SalesRule/Model/Rule/Condition/Product.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index e17cc9b16535e..8a9e6f7f2b66c 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -5,6 +5,8 @@ */ namespace Magento\SalesRule\Model\Rule\Condition; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; + /** * Product rule condition data model * @@ -45,7 +47,7 @@ protected function getProductToValidate(\Magento\Framework\Model\AbstractModel $ $attrCode = $this->getAttribute(); /* Check for attributes which are not available for configurable products */ - if ($product->isComposite() && !$product->hasData($attrCode)) { + if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) { /** @var \Magento\Catalog\Api\Data\ProductInterface $childProduct */ $childProduct = current($model->getChildren())->getProduct(); if ($childProduct->hasData($attrCode)) { From 9a35b459f1b31b2b8d40c6597bd90ac9c5c865fe Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Wed, 4 Jul 2018 22:57:37 +0300 Subject: [PATCH 05/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Made getProductToValidate method private according to Technical Guideline (2.7) --- app/code/Magento/SalesRule/Model/Rule/Condition/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index 8a9e6f7f2b66c..07a2ea1a87b6e 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -36,7 +36,7 @@ protected function _addSpecialAttributes(array &$attributes) * @return \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product * @throws \Magento\Framework\Exception\NoSuchEntityException */ - protected function getProductToValidate(\Magento\Framework\Model\AbstractModel $model) + private function getProductToValidate(\Magento\Framework\Model\AbstractModel $model) { /** @var \Magento\Catalog\Model\Product $product */ $product = $model->getProduct(); From 887ee4aa918340a5933c9923c334cef6b97d44eb Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Sat, 7 Jul 2018 22:10:05 +0300 Subject: [PATCH 06/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Added configurable product to dependencies --- app/code/Magento/SalesRule/composer.json | 3 ++- app/code/Magento/SalesRule/etc/module.xml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json index f030482bcf240..e282e035ad23f 100644 --- a/app/code/Magento/SalesRule/composer.json +++ b/app/code/Magento/SalesRule/composer.json @@ -19,7 +19,8 @@ "magento/module-widget": "101.0.*", "magento/module-quote": "101.0.*", "magento/module-ui": "101.0.*", - "magento/framework": "101.0.*" + "magento/framework": "101.0.*", + "magento/module-configurable-product": "100.*" }, "suggest": { "magento/module-sales-rule-sample-data": "Sample Data version:100.2.*" diff --git a/app/code/Magento/SalesRule/etc/module.xml b/app/code/Magento/SalesRule/etc/module.xml index f3f160eb7d40b..1df09b97b9353 100644 --- a/app/code/Magento/SalesRule/etc/module.xml +++ b/app/code/Magento/SalesRule/etc/module.xml @@ -12,6 +12,7 @@ + From 0c9aa81d514717a4761c716260130e87fb08980e Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Sun, 22 Jul 2018 12:30:36 +0300 Subject: [PATCH 07/34] Revert "#14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Added configurable product to dependencies" This reverts commit 887ee4a --- app/code/Magento/SalesRule/composer.json | 3 +-- app/code/Magento/SalesRule/etc/module.xml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json index e282e035ad23f..f030482bcf240 100644 --- a/app/code/Magento/SalesRule/composer.json +++ b/app/code/Magento/SalesRule/composer.json @@ -19,8 +19,7 @@ "magento/module-widget": "101.0.*", "magento/module-quote": "101.0.*", "magento/module-ui": "101.0.*", - "magento/framework": "101.0.*", - "magento/module-configurable-product": "100.*" + "magento/framework": "101.0.*" }, "suggest": { "magento/module-sales-rule-sample-data": "Sample Data version:100.2.*" diff --git a/app/code/Magento/SalesRule/etc/module.xml b/app/code/Magento/SalesRule/etc/module.xml index 1df09b97b9353..f3f160eb7d40b 100644 --- a/app/code/Magento/SalesRule/etc/module.xml +++ b/app/code/Magento/SalesRule/etc/module.xml @@ -12,7 +12,6 @@ - From 5b95b223b6bb3aa6ee292364486837a51e74ce31 Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Sun, 22 Jul 2018 12:47:17 +0300 Subject: [PATCH 08/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Restored \Magento\SalesRule\Model\Rule\Condition\Product to its previous state except PHPDocs. --- .../Model/Rule/Condition/Product.php | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php index 18baa786c942b..0b8b7fc046a24 100644 --- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php @@ -6,8 +6,6 @@ namespace Magento\SalesRule\Model\Rule\Condition; -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; - /** * Product rule condition data model * @@ -31,34 +29,6 @@ protected function _addSpecialAttributes(array &$attributes) $attributes['quote_item_row_total'] = __('Row total in cart'); } - /** - * @param \Magento\Framework\Model\AbstractModel $model - * - * @return \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product - * @throws \Magento\Framework\Exception\NoSuchEntityException - */ - private function getProductToValidate(\Magento\Framework\Model\AbstractModel $model) - { - /** @var \Magento\Catalog\Model\Product $product */ - $product = $model->getProduct(); - if (!$product instanceof \Magento\Catalog\Model\Product) { - $product = $this->productRepository->getById($model->getProductId()); - } - - $attrCode = $this->getAttribute(); - - /* Check for attributes which are not available for configurable products */ - if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) { - /** @var \Magento\Catalog\Api\Data\ProductInterface $childProduct */ - $childProduct = current($model->getChildren())->getProduct(); - if ($childProduct->hasData($attrCode)) { - $product = $childProduct; - } - } - - return $product; - } - /** * Validate Product Rule Condition * @@ -71,7 +41,10 @@ public function validate(\Magento\Framework\Model\AbstractModel $model) { //@todo reimplement this method when is fixed MAGETWO-5713 /** @var \Magento\Catalog\Model\Product $product */ - $product = $this->getProductToValidate($model); + $product = $model->getProduct(); + if (!$product instanceof \Magento\Catalog\Model\Product) { + $product = $this->productRepository->getById($model->getProductId()); + } $product->setQuoteItemQty( $model->getQty() From 618f408b2af3ff6c541cdc90d110de0a5827a66a Mon Sep 17 00:00:00 2001 From: MaxNovik Date: Sun, 22 Jul 2018 13:35:11 +0300 Subject: [PATCH 09/34] Moved adjustments to plugin. --- .../Model/Rule/Condition/Product.php | 54 +++++++++++++++++++ .../Magento/ConfigurableProduct/composer.json | 1 + .../Magento/ConfigurableProduct/etc/di.xml | 3 ++ 3 files changed, 58 insertions(+) create mode 100644 app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php new file mode 100644 index 0000000000000..a2fe0be4a7523 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php @@ -0,0 +1,54 @@ +setProduct( + $this->getProductToValidate($subject, $model) + ); + } + + + /** + * @param \Magento\SalesRule\Model\Rule\Condition\Product $subject + * @param \Magento\Framework\Model\AbstractModel $model + * + * @return \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product + */ + private function getProductToValidate( + \Magento\SalesRule\Model\Rule\Condition\Product $subject, + \Magento\Framework\Model\AbstractModel $model + ) { + /** @var \Magento\Catalog\Model\Product $product */ + $product = $model->getProduct(); + + $attrCode = $subject->getAttribute(); + + /* Check for attributes which are not available for configurable products */ + if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) { + /** @var \Magento\Catalog\Model\AbstractModel $childProduct */ + $childProduct = current($model->getChildren())->getProduct(); + if ($childProduct->hasData($attrCode)) { + $product = $childProduct; + } + } + + return $product; + } +} diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json index 4c583d79ce418..f2818883a131b 100644 --- a/app/code/Magento/ConfigurableProduct/composer.json +++ b/app/code/Magento/ConfigurableProduct/composer.json @@ -19,6 +19,7 @@ "suggest": { "magento/module-webapi": "100.2.*", "magento/module-sales": "101.0.*", + "magento/module-sales-rule": "101.0.*", "magento/module-product-video": "100.2.*", "magento/module-configurable-sample-data": "Sample Data version:100.2.*", "magento/module-product-links-sample-data": "Sample Data version:100.2.*" diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index 43e70f3766dca..d19fa7dcb29fe 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -221,4 +221,7 @@ + + + From 7c8482bccf6d6d55d89b743dc74f00278c9b8f95 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Mon, 23 Jul 2018 10:32:40 +0300 Subject: [PATCH 10/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products Removed an empty line. --- .../Plugin/SalesRule/Model/Rule/Condition/Product.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php index a2fe0be4a7523..183d21b0bddcb 100644 --- a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php @@ -24,7 +24,6 @@ public function beforeValidate( ); } - /** * @param \Magento\SalesRule\Model\Rule\Condition\Product $subject * @param \Magento\Framework\Model\AbstractModel $model From 8d417ac4192cdddb191686c5de8b18e5cda99032 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Thu, 9 Aug 2018 16:06:07 +0300 Subject: [PATCH 11/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Unit tests coverage: case when child should be used --- .../Model/Rule/Condition/ProductTest.php | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php new file mode 100644 index 0000000000000..4478c225dedfa --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php @@ -0,0 +1,198 @@ +objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->validator = $this->createValidator(); + $this->validatorPlugin = $this->objectManager->getObject(ValidatorPlugin::class); + } + + /** + * @return \Magento\SalesRule\Model\Rule\Condition\Product + */ + private function createValidator(): SalesRuleProduct + { + /** @var Context|\PHPUnit_Framework_MockObject_MockObject $contextMock */ + $contextMock = $this->getMockBuilder(Context::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var Data|\PHPUnit_Framework_MockObject_MockObject $backendHelperMock */ + $backendHelperMock = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var Config|\PHPUnit_Framework_MockObject_MockObject $configMock */ + $configMock = $this->getMockBuilder(Config::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var ProductFactory|\PHPUnit_Framework_MockObject_MockObject $productFactoryMock */ + $productFactoryMock = $this->getMockBuilder(ProductFactory::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $productRepositoryMock */ + $productRepositoryMock = $this->getMockBuilder(ProductRepositoryInterface::class) + ->getMockForAbstractClass(); + $attributeLoaderInterfaceMock = $this->getMockBuilder(AbstractEntity::class) + ->disableOriginalConstructor() + ->setMethods(['getAttributesByCode']) + ->getMock(); + $attributeLoaderInterfaceMock + ->expects($this->any()) + ->method('getAttributesByCode') + ->willReturn([]); + /** @var Product|\PHPUnit_Framework_MockObject_MockObject $productMock */ + $productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['loadAllAttributes', 'getConnection', 'getTable']) + ->getMock(); + $productMock->expects($this->any()) + ->method('loadAllAttributes') + ->willReturn($attributeLoaderInterfaceMock); + /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + $collectionMock = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var FormatInterface|\PHPUnit_Framework_MockObject_MockObject $formatMock */ + $formatMock = new Format( + $this->getMockBuilder(ScopeResolverInterface::class)->disableOriginalConstructor()->getMock(), + $this->getMockBuilder(ResolverInterface::class)->disableOriginalConstructor()->getMock(), + $this->getMockBuilder(CurrencyFactory::class)->disableOriginalConstructor()->getMock() + ); + + return new SalesRuleProduct( + $contextMock, + $backendHelperMock, + $configMock, + $productFactoryMock, + $productRepositoryMock, + $productMock, + $collectionMock, + $formatMock + ); + } + + public function testChildIsUsedForValidation() + { + $configurableProductMock = $this->createProductMock(); + $configurableProductMock + ->expects($this->any()) + ->method('getTypeId') + ->willReturn(Configurable::TYPE_CODE); + $configurableProductMock + ->expects($this->any()) + ->method('hasData') + ->with($this->equalTo('special_price')) + ->willReturn(false); + + /* @var AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */ + $item = $this->getMockBuilder(AbstractItem::class) + ->disableOriginalConstructor() + ->setMethods(['setProduct', 'getProduct', 'getChildren']) + ->getMockForAbstractClass(); + $item->expects($this->any()) + ->method('getProduct') + ->willReturn($configurableProductMock); + + $simpleProductMock = $this->createProductMock(); + $simpleProductMock + ->expects($this->any()) + ->method('getTypeId') + ->willReturn(Type::TYPE_SIMPLE); + $simpleProductMock + ->expects($this->any()) + ->method('hasData') + ->with($this->equalTo('special_price')) + ->willReturn(true); + + $childItem = $this->getMockBuilder(AbstractItem::class) + ->disableOriginalConstructor() + ->setMethods(['getProduct']) + ->getMockForAbstractClass(); + $childItem->expects($this->any()) + ->method('getProduct') + ->willReturn($simpleProductMock); + + $item->expects($this->any()) + ->method('getChildren') + ->willReturn([$childItem]); + $item->expects($this->once()) + ->method('setProduct') + ->with($simpleProductMock); + + $this->validator->setAttribute('special_price'); + + $this->validatorPlugin->beforeValidate($this->validator, $item); + } + + /** + * @return Product|\PHPUnit_Framework_MockObject_MockObject + */ + private function createProductMock(): \PHPUnit_Framework_MockObject_MockObject + { + $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->setMethods([ + 'getAttribute', + 'getId', + 'setQuoteItemQty', + 'setQuoteItemPrice', + 'getTypeId', + 'hasData', + ]) + ->getMock(); + $productMock + ->expects($this->any()) + ->method('setQuoteItemQty') + ->willReturnSelf(); + $productMock + ->expects($this->any()) + ->method('setQuoteItemPrice') + ->willReturnSelf(); + + return $productMock; + } +} From 90ff989212c73ee31b75c06d1f9c14efae4715aa Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Thu, 9 Aug 2018 16:49:51 +0300 Subject: [PATCH 12/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Fixed mock objects comparison --- .../Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php index 4478c225dedfa..f7efb97a1d75a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php @@ -161,7 +161,7 @@ public function testChildIsUsedForValidation() ->willReturn([$childItem]); $item->expects($this->once()) ->method('setProduct') - ->with($simpleProductMock); + ->with($this->identicalTo($simpleProductMock)); $this->validator->setAttribute('special_price'); From c52e0e856f5edb657867d65fcf88702eef00ca37 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Thu, 9 Aug 2018 17:00:27 +0300 Subject: [PATCH 13/34] Covered case when simple product is being validated --- .../Model/Rule/Condition/ProductTest.php | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php index f7efb97a1d75a..50200a6707d96 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php @@ -90,8 +90,8 @@ private function createValidator(): SalesRuleProduct ->setMethods(['loadAllAttributes', 'getConnection', 'getTable']) ->getMock(); $productMock->expects($this->any()) - ->method('loadAllAttributes') - ->willReturn($attributeLoaderInterfaceMock); + ->method('loadAllAttributes') + ->willReturn($attributeLoaderInterfaceMock); /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ $collectionMock = $this->getMockBuilder(Collection::class) ->disableOriginalConstructor() @@ -195,4 +195,35 @@ private function createProductMock(): \PHPUnit_Framework_MockObject_MockObject return $productMock; } + + public function testChildIsNotUsedForValidation() + { + $simpleProductMock = $this->createProductMock(); + $simpleProductMock + ->expects($this->any()) + ->method('getTypeId') + ->willReturn(Type::TYPE_SIMPLE); + $simpleProductMock + ->expects($this->any()) + ->method('hasData') + ->with($this->equalTo('special_price')) + ->willReturn(true); + + /* @var AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */ + $item = $this->getMockBuilder(AbstractItem::class) + ->disableOriginalConstructor() + ->setMethods(['setProduct', 'getProduct']) + ->getMockForAbstractClass(); + $item->expects($this->any()) + ->method('getProduct') + ->willReturn($simpleProductMock); + + $item->expects($this->once()) + ->method('setProduct') + ->with($this->identicalTo($simpleProductMock)); + + $this->validator->setAttribute('special_price'); + + $this->validatorPlugin->beforeValidate($this->validator, $item); + } } From 5c3154b665f1843ab8de50396a9fe739b021cea6 Mon Sep 17 00:00:00 2001 From: Maksym Novik Date: Thu, 9 Aug 2018 23:18:36 +0300 Subject: [PATCH 14/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does-not-work-for-configurable-products. Fixed static tests. --- .../Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php index 50200a6707d96..b1fc09e9676a2 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Plugin\SalesRule\Model\Rule\Condition; +namespace Magento\ConfigurableProduct\Test\Unit\Plugin\SalesRule\Model\Rule\Condition; use Magento\Backend\Helper\Data; use Magento\Catalog\Api\ProductRepositoryInterface; @@ -27,6 +27,7 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.LongVariable) */ class ProductTest extends \PHPUnit\Framework\TestCase { From 24de687c16d5ce007336f01d70fb9ed800838a00 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Thu, 4 Oct 2018 14:19:33 +0300 Subject: [PATCH 15/34] ENGCOM-2111: Fix static test failure. --- .../Plugin/SalesRule/Model/Rule/Condition/Product.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php index 183d21b0bddcb..906356c84ebac 100644 --- a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php @@ -1,4 +1,9 @@ - Date: Thu, 25 Oct 2018 18:02:22 +0530 Subject: [PATCH 16/34] fixed Quote Item Prices are NULL in cart related events. #18685 --- app/code/Magento/Quote/Model/Quote/Item/Processor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/Model/Quote/Item/Processor.php b/app/code/Magento/Quote/Model/Quote/Item/Processor.php index f9dac1779ad27..38a16f926d12d 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/Processor.php +++ b/app/code/Magento/Quote/Model/Quote/Item/Processor.php @@ -95,7 +95,7 @@ public function prepare(Item $item, DataObject $request, Product $candidate) $item->setData(CartItemInterface::KEY_QTY, 0); } $item->addQty($candidate->getCartQty()); - + $item->setPrice($item->getProduct()->getFinalPrice()); $customPrice = $request->getCustomPrice(); if (!empty($customPrice)) { $item->setCustomPrice($customPrice); From 1638891a11aeab7673d6e0280f43ff864486406a Mon Sep 17 00:00:00 2001 From: ashutosh Date: Sun, 28 Oct 2018 15:47:48 +0530 Subject: [PATCH 17/34] fixed unit test issues --- .../Quote/Model/Quote/Item/Processor.php | 3 +- .../Unit/Model/Quote/Item/ProcessorTest.php | 33 +++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Quote/Model/Quote/Item/Processor.php b/app/code/Magento/Quote/Model/Quote/Item/Processor.php index 38a16f926d12d..757b81b984a46 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/Processor.php +++ b/app/code/Magento/Quote/Model/Quote/Item/Processor.php @@ -95,8 +95,9 @@ public function prepare(Item $item, DataObject $request, Product $candidate) $item->setData(CartItemInterface::KEY_QTY, 0); } $item->addQty($candidate->getCartQty()); - $item->setPrice($item->getProduct()->getFinalPrice()); + $customPrice = $request->getCustomPrice(); + $item->setPrice($candidate->getFinalPrice()); if (!empty($customPrice)) { $item->setCustomPrice($customPrice); $item->setOriginalCustomPrice($customPrice); diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php index a56de35b70f75..7da7ed49149f7 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php @@ -76,7 +76,8 @@ protected function setUp() 'addQty', 'setCustomPrice', 'setOriginalCustomPrice', - 'setData' + 'setData', + 'setprice' ]); $this->quoteItemFactoryMock->expects($this->any()) ->method('create') @@ -98,7 +99,7 @@ protected function setUp() $this->productMock = $this->createPartialMock( \Magento\Catalog\Model\Product::class, - ['getCustomOptions', '__wakeup', 'getParentProductId', 'getCartQty', 'getStickWithinParent'] + ['getCustomOptions', '__wakeup', 'getParentProductId', 'getCartQty', 'getStickWithinParent', 'getFinalPrice'] ); $this->objectMock = $this->createPartialMock( \Magento\Framework\DataObject::class, @@ -239,6 +240,7 @@ public function testPrepare() $customPrice = 400000000; $itemId = 1; $requestItemId = 1; + $finalPrice = 1000000000; $this->productMock->expects($this->any()) ->method('getCartQty') @@ -246,6 +248,9 @@ public function testPrepare() $this->productMock->expects($this->any()) ->method('getStickWithinParent') ->will($this->returnValue(false)); + $this->productMock->expects($this->once()) + ->method('getFinalPrice') + ->will($this->returnValue($finalPrice)); $this->itemMock->expects($this->once()) ->method('addQty') @@ -255,6 +260,9 @@ public function testPrepare() ->will($this->returnValue($itemId)); $this->itemMock->expects($this->never()) ->method('setData'); + $this->itemMock->expects($this->once()) + ->method('setPrice') + ->will($this->returnValue($this->itemMock)); $this->objectMock->expects($this->any()) ->method('getCustomPrice') @@ -282,6 +290,7 @@ public function testPrepareWithResetCountAndStick() $customPrice = 400000000; $itemId = 1; $requestItemId = 1; + $finalPrice = 1000000000; $this->productMock->expects($this->any()) ->method('getCartQty') @@ -289,6 +298,9 @@ public function testPrepareWithResetCountAndStick() $this->productMock->expects($this->any()) ->method('getStickWithinParent') ->will($this->returnValue(true)); + $this->productMock->expects($this->once()) + ->method('getFinalPrice') + ->will($this->returnValue($finalPrice)); $this->itemMock->expects($this->once()) ->method('addQty') @@ -298,6 +310,9 @@ public function testPrepareWithResetCountAndStick() ->will($this->returnValue($itemId)); $this->itemMock->expects($this->never()) ->method('setData'); + $this->itemMock->expects($this->once()) + ->method('setPrice') + ->will($this->returnValue($this->itemMock)); $this->objectMock->expects($this->any()) ->method('getCustomPrice') @@ -325,6 +340,7 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId() $customPrice = 400000000; $itemId = 1; $requestItemId = 2; + $finalPrice = 1000000000; $this->productMock->expects($this->any()) ->method('getCartQty') @@ -332,6 +348,9 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId() $this->productMock->expects($this->any()) ->method('getStickWithinParent') ->will($this->returnValue(false)); + $this->productMock->expects($this->once()) + ->method('getFinalPrice') + ->will($this->returnValue($finalPrice)); $this->itemMock->expects($this->once()) ->method('addQty') @@ -341,6 +360,9 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId() ->will($this->returnValue($itemId)); $this->itemMock->expects($this->never()) ->method('setData'); + $this->itemMock->expects($this->once()) + ->method('setPrice') + ->will($this->returnValue($this->itemMock)); $this->objectMock->expects($this->any()) ->method('getCustomPrice') @@ -368,6 +390,7 @@ public function testPrepareWithResetCountAndNotStickAndSameItemId() $customPrice = 400000000; $itemId = 1; $requestItemId = 1; + $finalPrice = 1000000000; $this->objectMock->expects($this->any()) ->method('getResetCount') @@ -386,10 +409,16 @@ public function testPrepareWithResetCountAndNotStickAndSameItemId() $this->productMock->expects($this->any()) ->method('getStickWithinParent') ->will($this->returnValue(false)); + $this->productMock->expects($this->once()) + ->method('getFinalPrice') + ->will($this->returnValue($finalPrice)); $this->itemMock->expects($this->once()) ->method('addQty') ->with($qty); + $this->itemMock->expects($this->once()) + ->method('setPrice') + ->will($this->returnValue($this->itemMock)); $this->objectMock->expects($this->any()) ->method('getCustomPrice') From 175ebc0bbc8cf2e4a5e4fabc59626cdfaf7aa519 Mon Sep 17 00:00:00 2001 From: ashutosh Date: Tue, 30 Oct 2018 02:05:48 +0530 Subject: [PATCH 18/34] fixed phpcs issue: Line exceeds maximum limit of 120 characters; contains 121 --- .../Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php index 7da7ed49149f7..0b4b167d2472e 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php @@ -99,7 +99,13 @@ protected function setUp() $this->productMock = $this->createPartialMock( \Magento\Catalog\Model\Product::class, - ['getCustomOptions', '__wakeup', 'getParentProductId', 'getCartQty', 'getStickWithinParent', 'getFinalPrice'] + [ + 'getCustomOptions', + '__wakeup', + 'getParentProductId', + 'getCartQty', + 'getStickWithinParent', + 'getFinalPrice'] ); $this->objectMock = $this->createPartialMock( \Magento\Framework\DataObject::class, From 59bd87487dfc5f1ea69247b8b3ab7faee4ca486c Mon Sep 17 00:00:00 2001 From: ashutosh Date: Tue, 30 Oct 2018 15:37:19 +0530 Subject: [PATCH 19/34] error fixed Whitespace found at end of line --- .../Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php index 0b4b167d2472e..e8cfb05ca89b9 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php @@ -100,11 +100,11 @@ protected function setUp() $this->productMock = $this->createPartialMock( \Magento\Catalog\Model\Product::class, [ - 'getCustomOptions', - '__wakeup', - 'getParentProductId', - 'getCartQty', - 'getStickWithinParent', + 'getCustomOptions', + '__wakeup', + 'getParentProductId', + 'getCartQty', + 'getStickWithinParent', 'getFinalPrice'] ); $this->objectMock = $this->createPartialMock( From fc81559a3dc306dbb9f501ed2e2f1d64f824c967 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 30 Oct 2018 12:36:05 +0200 Subject: [PATCH 20/34] ENGCOM-2111: Performance improved. --- .../Plugin/SalesRule/Model/Rule/Condition/Product.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php index 906356c84ebac..80bb503a8c250 100644 --- a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php @@ -24,9 +24,10 @@ public function beforeValidate( \Magento\SalesRule\Model\Rule\Condition\Product $subject, \Magento\Framework\Model\AbstractModel $model ) { - $model->setProduct( - $this->getProductToValidate($subject, $model) - ); + $product = $this->getProductToValidate($subject, $model); + if ($model->getProduct() !== $product) { + $model->setProduct($product); + } } /** From a2399004d048ef3543befe3caeac67bc00d65d15 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 31 Oct 2018 15:58:03 +0200 Subject: [PATCH 21/34] ENGCOM-2111: Fix empty minicart bug. --- .../Plugin/SalesRule/Model/Rule/Condition/Product.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php index 80bb503a8c250..34e04c107d0a8 100644 --- a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php +++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php @@ -26,8 +26,13 @@ public function beforeValidate( ) { $product = $this->getProductToValidate($subject, $model); if ($model->getProduct() !== $product) { - $model->setProduct($product); + // We need to replace product only for validation and keep original product for all other cases. + $clone = clone $model; + $clone->setProduct($product); + $model = $clone; } + + return [$model]; } /** From 1c01be80816b63bc86f0e7e5796de2f33cbaab09 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 7 Nov 2018 13:31:55 +0200 Subject: [PATCH 22/34] ENGCOM-3271: Update api-functional test. --- .../testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php | 1 + 1 file changed, 1 insertion(+) 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 18f57515c4d18..268cb72e25f8d 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php @@ -70,6 +70,7 @@ public function testAddProductToCartWithCustomOptions() 'custom_options' => $this->getOptions(), ], ], + 'price' => $item->getPrice(), ], $response ); From 541bc6932365292525dc9d0b84bc589177198c1d Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 13 Nov 2018 16:12:47 +0200 Subject: [PATCH 23/34] ENGCOM-3271: Quote Item table upgrade script added. --- .../ConfigurableProduct/Setup/UpgradeData.php | 36 +++++++++++++++++-- .../ConfigurableProduct/etc/module.xml | 2 +- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php index 62ad21a24ac7e..1ff78a632c3bb 100644 --- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php +++ b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php @@ -7,11 +7,11 @@ use Magento\Catalog\Model\Product; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -use Magento\Framework\Setup\UpgradeDataInterface; -use Magento\Framework\Setup\ModuleContextInterface; -use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\ModuleDataSetupInterface; +use Magento\Framework\Setup\UpgradeDataInterface; /** * Upgrade Data script @@ -62,6 +62,10 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface } } + if (version_compare($context->getVersion(), '2.2.2', '<')) { + $this->upgradeQuoteItemPrice($setup); + } + $setup->endSetup(); } @@ -97,4 +101,30 @@ private function updateRelatedProductTypes(string $attributeId, array $relatedPr implode(',', $relatedProductTypes) ); } + + /** + * Update 'price' value for quote items without price of configurable products subproducts. + * + * @param ModuleDataSetupInterface $setup + */ + private function upgradeQuoteItemPrice(ModuleDataSetupInterface $setup) + { + $connection = $setup->getConnection(); + $quoteItemTable = $setup->getTable('quote_item'); + $select = $connection->select(); + $select->joinLeft( + ['qi2' => $quoteItemTable], + 'qi1.parent_item_id = qi2.item_id', + ['price'] + )->where( + 'qi1.price = 0' + . ' AND qi1.parent_item_id IS NOT NULL' + . ' AND qi2.product_type = "' . Configurable::TYPE_CODE . '"' + ); + $updateQuoteItem = $setup->getConnection()->updateFromSelect( + $select, + ['qi1' => $quoteItemTable] + ); + $setup->getConnection()->query($updateQuoteItem); + } } diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml index 0b971ef775e16..b7d4c92aaa992 100644 --- a/app/code/Magento/ConfigurableProduct/etc/module.xml +++ b/app/code/Magento/ConfigurableProduct/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + From a9ac1c4eb26773f2482430f922724c815d26f084 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Thu, 15 Nov 2018 10:42:17 +0200 Subject: [PATCH 24/34] Covering the AddPaymentWeeeItem and SetWeeeRendererInFormObserver by Unit Tests --- .../Unit/Observer/AddPaymentWeeeItemTest.php | 146 ++++++++++++++++++ .../SetWeeeRendererInFormObserverTest.php | 79 ++++++++++ 2 files changed, 225 insertions(+) create mode 100644 app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php create mode 100644 app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php diff --git a/app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php b/app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php new file mode 100644 index 0000000000000..d19d6000112ed --- /dev/null +++ b/app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php @@ -0,0 +1,146 @@ +weeeHelperMock = $this->createMock(Data::class); + $this->storeManagerMock = $this->createMock(StoreManagerInterface::class); + + $this->observer = new AddPaymentWeeeItem( + $this->weeeHelperMock, + $this->storeManagerMock + ); + } + + /** + * Test execute + * + * @dataProvider dataProvider + * @param bool $isEnabled + * @param bool $includeInSubtotal + * @return void + */ + public function testExecute(bool $isEnabled, bool $includeInSubtotal) + { + /** @var Observer|MockObject $observerMock */ + $observerMock = $this->createMock(Observer::class); + $cartModelMock = $this->createMock(Cart::class); + $salesModelMock = $this->createMock(SalesModelInterface::class); + $itemMock = $this->createPartialMock(Item::class, ['getOriginalItem']); + $originalItemMock = $this->createPartialMock(Item::class, ['getParentItem']); + $parentItemMock = $this->createMock(Item::class); + $eventMock = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->setMethods(['getCart']) + ->getMock(); + + $asCustomItem = $this->prepareShouldBeAddedAsCustomItem($isEnabled, $includeInSubtotal); + $toBeCalled = 1; + if (!$asCustomItem) { + $toBeCalled = 0; + } + + $eventMock->expects($this->atLeast($toBeCalled)) + ->method('getCart') + ->willReturn($cartModelMock); + $observerMock->expects($this->atLeast($toBeCalled)) + ->method('getEvent') + ->willReturn($eventMock); + $itemMock->expects($this->atLeast($toBeCalled)) + ->method('getOriginalItem') + ->willReturn($originalItemMock); + $originalItemMock->expects($this->atLeast($toBeCalled)) + ->method('getParentItem') + ->willReturn($parentItemMock); + $salesModelMock->expects($this->atLeast($toBeCalled)) + ->method('getAllItems') + ->willReturn([$itemMock]); + $cartModelMock->expects($this->atLeast($toBeCalled)) + ->method('getSalesModel') + ->willReturn($salesModelMock); + + $this->observer->execute($observerMock); + } + + /** + * @return array + */ + public function dataProvider(): array + { + return [ + [true, false], + [true, true], + [false, true], + [false, false], + ]; + } + + /** + * Prepare if FPT should be added to payment cart as custom item or not. + * + * @param bool $isEnabled + * @param bool $includeInSubtotal + * @return bool + */ + private function prepareShouldBeAddedAsCustomItem(bool $isEnabled, bool $includeInSubtotal): bool + { + $storeMock = $this->getMockBuilder(StoreInterface::class) + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $storeMock->method('getId')->willReturn(Store::DEFAULT_STORE_ID); + $this->storeManagerMock->method('getStore')->willReturn($storeMock); + $this->weeeHelperMock->method('isEnabled')->with(Store::DEFAULT_STORE_ID) + ->willReturn($isEnabled); + + if ($isEnabled) { + $this->weeeHelperMock->method('includeInSubtotal')->with(Store::DEFAULT_STORE_ID) + ->willReturn($includeInSubtotal); + } + + return $isEnabled && !$includeInSubtotal; + } +} diff --git a/app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php b/app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php new file mode 100644 index 0000000000000..f9f39aa8ebf6f --- /dev/null +++ b/app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php @@ -0,0 +1,79 @@ +layoutMock = $this->createMock(LayoutInterface::class); + $this->taxModelMock = $this->createMock(Tax::class); + $this->observer = new SetWeeeRendererInFormObserver( + $this->layoutMock, + $this->taxModelMock + ); + } + + /** + * Test assigning a custom renderer for product create/edit form weee attribute element + * + * @return void + */ + public function testExecute() + { + $attributes = new \ArrayIterator(['element_code_1', 'element_code_2']); + /** @var Event|MockObject $eventMock */ + $eventMock = $this->getMockBuilder(Event::class)->disableOriginalConstructor() + ->setMethods(['getForm']) + ->getMock(); + + /** @var Observer|MockObject $observerMock */ + $observerMock = $this->createMock(Observer::class); + /** @var Form|MockObject $formMock */ + $formMock = $this->createMock(Form::class); + + $eventMock->method('getForm')->willReturn($formMock); + $observerMock->method('getEvent')->willReturn($eventMock); + $this->taxModelMock->method('getWeeeAttributeCodes')->willReturn($attributes); + $formMock->expects($this->exactly($attributes->count()))->method('getElement')->willReturnSelf(); + + $this->observer->execute($observerMock); + } +} From 7415cdd6de3c8e49792bebf364556530d7409eb5 Mon Sep 17 00:00:00 2001 From: eduard13 Date: Thu, 15 Nov 2018 10:52:27 +0200 Subject: [PATCH 25/34] Covering the CheckUserLoginBackendObserver by Unit Test --- .../CheckUserLoginBackendObserverTest.php | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php new file mode 100644 index 0000000000000..6966bd4cce7f9 --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php @@ -0,0 +1,137 @@ +helperMock = $this->createMock(Data::class); + $this->messageManagerMock = $this->createMock(ManagerInterface::class); + $this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class); + $this->requestMock = $this->createMock(RequestInterface::class); + + $this->observer = new CheckUserLoginBackendObserver( + $this->helperMock, + $this->captchaStringResolverMock, + $this->requestMock + ); + } + + /** + * Test check user login in backend with correct captcha + * + * @dataProvider requiredCaptchaDataProvider + * @param bool $isRequired + * @return void + */ + public function testCheckOnBackendLoginWithCorrectCaptcha(bool $isRequired) + { + $formId = 'backend_login'; + $login = 'admin'; + $captchaValue = 'captcha-value'; + + /** @var Observer|MockObject $observerMock */ + $observerMock = $this->createPartialMock(Observer::class, ['getEvent']); + $eventMock = $this->createPartialMock(Event::class, ['getUsername']); + $captcha = $this->createMock(DefaultModel::class); + + $eventMock->method('getUsername')->willReturn('admin'); + $observerMock->method('getEvent')->willReturn($eventMock); + $captcha->method('isRequired')->with($login)->willReturn($isRequired); + $captcha->method('isCorrect')->with($captchaValue)->willReturn(true); + $this->helperMock->method('getCaptcha')->with($formId)->willReturn($captcha); + $this->captchaStringResolverMock->method('resolve')->with($this->requestMock, $formId) + ->willReturn($captchaValue); + + $this->observer->execute($observerMock); + } + + /** + * @return array + */ + public function requiredCaptchaDataProvider(): array + { + return [ + [true], + [false] + ]; + } + + /** + * Test check user login in backend with wrong captcha + * + * @return void + * @expectedException \Magento\Framework\Exception\Plugin\AuthenticationException + */ + public function testCheckOnBackendLoginWithWrongCaptcha() + { + $formId = 'backend_login'; + $login = 'admin'; + $captchaValue = 'captcha-value'; + + /** @var Observer|MockObject $observerMock */ + $observerMock = $this->createPartialMock(Observer::class, ['getEvent']); + $eventMock = $this->createPartialMock(Event::class, ['getUsername']); + $captcha = $this->createMock(DefaultModel::class); + + $eventMock->method('getUsername')->willReturn($login); + $observerMock->method('getEvent')->willReturn($eventMock); + $captcha->method('isRequired')->with($login)->willReturn(true); + $captcha->method('isCorrect')->with($captchaValue)->willReturn(false); + $this->helperMock->method('getCaptcha')->with($formId)->willReturn($captcha); + $this->captchaStringResolverMock->method('resolve')->with($this->requestMock, $formId) + ->willReturn($captchaValue); + + $this->observer->execute($observerMock); + } +} From aa4abec4a587b6054c01c36542e97037cea8b7b1 Mon Sep 17 00:00:00 2001 From: larsroettig Date: Tue, 30 Oct 2018 21:32:40 +0100 Subject: [PATCH 26/34] #18956 Fixes for set root_category_id --- .../Magento/Store/Model/Config/Importer/Processor/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php index 0a3f5eb5f31a3..def2621732c90 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php @@ -176,8 +176,8 @@ private function createGroups(array $items, array $data) ); $group = $this->groupFactory->create(); - $group->setData($groupData); $group->setRootCategoryId(0); + $group->setData($groupData); $group->getResource()->save($group); $group->getResource()->addCommitCallback(function () use ($data, $group, $website) { From acefdb33b0b060c2080d0cc8c20008288afa33f7 Mon Sep 17 00:00:00 2001 From: Lars Roettig Date: Fri, 2 Nov 2018 15:34:08 +0100 Subject: [PATCH 27/34] CodeReviewChange --- .../Magento/Store/Model/Config/Importer/Processor/Create.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php index def2621732c90..ff473973cca9e 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php @@ -176,7 +176,10 @@ private function createGroups(array $items, array $data) ); $group = $this->groupFactory->create(); - $group->setRootCategoryId(0); + if (!isset($groupData['root_categry_id'])) { + $groupData['root_categry_id'] = 0; + } + $group->setData($groupData); $group->getResource()->save($group); From 5866a39705b817ca6ce49440cbe4d5894ac47063 Mon Sep 17 00:00:00 2001 From: larsroettig Date: Mon, 5 Nov 2018 00:19:04 +0100 Subject: [PATCH 28/34] #18956 Fix for phpunit-test case --- .../Magento/Store/Model/Config/Importer/Processor/Create.php | 4 ++-- .../Test/Unit/Model/Config/Importer/Processor/CreateTest.php | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php index ff473973cca9e..c96f18939e1f6 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php @@ -176,8 +176,8 @@ private function createGroups(array $items, array $data) ); $group = $this->groupFactory->create(); - if (!isset($groupData['root_categry_id'])) { - $groupData['root_categry_id'] = 0; + if (!isset($groupData['root_category_id'])) { + $groupData['root_category_id'] = 0; } $group->setData($groupData); diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php index 2c2b0b00aec43..0901464224399 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php @@ -291,9 +291,6 @@ public function testRunGroup() $this->groupMock->expects($this->exactly(3)) ->method('getResource') ->willReturn($this->abstractDbMock); - $this->groupMock->expects($this->once()) - ->method('setRootCategoryId') - ->with(0); $this->groupMock->expects($this->once()) ->method('getDefaultStoreId') ->willReturn($defaultStoreId); From fee27127882c0bf2ef832213fef737b259ed5619 Mon Sep 17 00:00:00 2001 From: larsroettig Date: Wed, 7 Nov 2018 20:35:28 +0100 Subject: [PATCH 29/34] #18956 Add TestCase for no root_category_id set --- .../Config/Importer/Processor/CreateTest.php | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php index 0901464224399..0fbf7bb7f044b 100644 --- a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php +++ b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php @@ -196,14 +196,30 @@ private function initTestData() 'root_category_id' => '1', 'default_store_id' => '1', 'code' => 'default', + ], + 2 => [ + 'group_id' => '1', + 'website_id' => '1', + 'name' => 'Default1', + 'default_store_id' => '1', + 'code' => 'default1', ] ]; - $this->trimmedGroup = [ - 'name' => 'Default', - 'root_category_id' => '1', - 'code' => 'default', - 'default_store_id' => '1', - ]; + $this->trimmedGroup = + [ + 0 => [ + 'name' => 'Default', + 'root_category_id' => '1', + 'code' => 'default', + 'default_store_id' => '1', + ], + 1 => [ + 'name' => 'Default1', + 'root_category_id' => '0', + 'code' => 'default1', + 'default_store_id' => '1' + ] + ]; $this->stores = [ 'default' => [ 'store_id' => '1', @@ -280,31 +296,34 @@ public function testRunGroup() [ScopeInterface::SCOPE_GROUPS, $this->groups, $this->groups], ]); - $this->websiteMock->expects($this->once()) + $this->websiteMock->expects($this->exactly(2)) ->method('getResource') ->willReturn($this->abstractDbMock); - $this->groupMock->expects($this->once()) + $this->groupMock->expects($this->exactly(2)) ->method('setData') - ->with($this->trimmedGroup) - ->willReturnSelf(); - $this->groupMock->expects($this->exactly(3)) + ->withConsecutive( + [$this->equalTo($this->trimmedGroup[0])], + [$this->equalTo($this->trimmedGroup[1])] + )->willReturnSelf(); + + $this->groupMock->expects($this->exactly(6)) ->method('getResource') ->willReturn($this->abstractDbMock); - $this->groupMock->expects($this->once()) + $this->groupMock->expects($this->exactly(2)) ->method('getDefaultStoreId') ->willReturn($defaultStoreId); - $this->groupMock->expects($this->once()) + $this->groupMock->expects($this->exactly(2)) ->method('setDefaultStoreId') ->with($storeId); - $this->groupMock->expects($this->once()) + $this->groupMock->expects($this->exactly(2)) ->method('setWebsite') ->with($this->websiteMock); - $this->storeMock->expects($this->once()) + $this->storeMock->expects($this->exactly(2)) ->method('getResource') ->willReturn($this->abstractDbMock); - $this->storeMock->expects($this->once()) + $this->storeMock->expects($this->exactly(2)) ->method('getStoreId') ->willReturn($storeId); @@ -312,11 +331,11 @@ public function testRunGroup() ->method('load') ->withConsecutive([$this->websiteMock, 'base', 'code'], [$this->storeMock, 'default', 'code']) ->willReturnSelf(); - $this->abstractDbMock->expects($this->exactly(2)) + $this->abstractDbMock->expects($this->exactly(4)) ->method('save') ->with($this->groupMock) ->willReturnSelf(); - $this->abstractDbMock->expects($this->once()) + $this->abstractDbMock->expects($this->exactly(2)) ->method('addCommitCallback') ->willReturnCallback(function ($function) { return $function(); From 7be21e2bac3ae2557fcd2ef1e747d0877417944d Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Thu, 8 Nov 2018 09:23:21 -0600 Subject: [PATCH 30/34] ENGCOM-3408: #18956 Fixes for set root_category_id #18958 - fixed docblocks --- .../Model/Config/Importer/Processor/Create.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php index c96f18939e1f6..c18ea47a21eb0 100644 --- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php +++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php @@ -16,8 +16,6 @@ /** * The processor for creating of new entities. - * - * {@inheritdoc} */ class Create implements ProcessorInterface { @@ -84,7 +82,9 @@ public function __construct( /** * Creates entities in application according to the data set. * - * {@inheritdoc} + * @param array $data The data to be processed + * @return void + * @throws RuntimeException If processor was unable to finish execution */ public function run(array $data) { @@ -229,8 +229,7 @@ private function createStores(array $items, array $data) } /** - * Searches through given websites and compares with current websites. - * Returns found website. + * Searches through given websites and compares with current websites and returns found website. * * @param array $data The data to be searched in * @param string $websiteId The website id @@ -252,8 +251,7 @@ private function detectWebsiteById(array $data, $websiteId) } /** - * Searches through given groups and compares with current websites. - * Returns found group. + * Searches through given groups and compares with current websites and returns found group. * * @param array $data The data to be searched in * @param string $groupId The group id @@ -275,8 +273,7 @@ private function detectGroupById(array $data, $groupId) } /** - * Searches through given stores and compares with current stores. - * Returns found store. + * Searches through given stores and compares with current stores and returns found store. * * @param array $data The data to be searched in * @param string $storeId The store id From 64718ce50a6c725b69b01a04d136e6df37db0eeb Mon Sep 17 00:00:00 2001 From: Dmytro Cheshun Date: Sun, 28 Oct 2018 11:42:31 +0200 Subject: [PATCH 31/34] Add missing unit test for WishlistSettings plugin --- .../Ui/DataProvider/WishlistSettingsTest.php | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php diff --git a/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php b/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php new file mode 100644 index 0000000000000..aa3b956e12153 --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php @@ -0,0 +1,59 @@ +helperMock = $this->createMock(Data::class); + $this->wishlistSettings = new WishlistSettings($this->helperMock); + } + + /** + * Test afterGetData method + * + * @return void + */ + public function testAfterGetData() + { + /** @var DataProvider|\PHPUnit_Framework_MockObject_MockObject $subjectMock */ + $subjectMock = $this->createMock(DataProvider::class); + $result = []; + $isAllow = true; + $this->helperMock->expects($this->once())->method('isAllow')->willReturn(true); + + $expected = ['allowWishlist' => $isAllow]; + $actual = $this->wishlistSettings->afterGetData($subjectMock, $result); + self::assertEquals($expected, $actual); + } +} From aa379ea60c5afbd020f72d53b2ccac1ffde753d9 Mon Sep 17 00:00:00 2001 From: Mahesh Singh Date: Sun, 18 Nov 2018 17:14:31 +0530 Subject: [PATCH 32/34] issue #19205 fixed --- app/code/Magento/Bundle/Model/Product/Type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index afcb09f2f43fe..b81f9f5d31bd6 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -822,7 +822,7 @@ private function multiToFlatArray(array $array) if (is_array($value)) { $flatArray = array_merge($flatArray, $this->multiToFlatArray($value)); } else { - $flatArray[$key] = $value; + $flatArray[] = $value; } } From 1a321d2fa30f031f4beb37d562a995aef94d5dd8 Mon Sep 17 00:00:00 2001 From: Mahesh Singh Date: Sun, 18 Nov 2018 18:55:08 +0530 Subject: [PATCH 33/34] removed unused variable --- app/code/Magento/Bundle/Model/Product/Type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index b81f9f5d31bd6..f85350b0cc3d6 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -818,7 +818,7 @@ private function recursiveIntval(array $array) private function multiToFlatArray(array $array) { $flatArray = []; - foreach ($array as $key => $value) { + foreach ($array as $value) { if (is_array($value)) { $flatArray = array_merge($flatArray, $this->multiToFlatArray($value)); } else { From 9945dc7552de8aa95d8eb03e53b84e0ff14a1650 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 21 Nov 2018 13:43:17 +0200 Subject: [PATCH 34/34] #14020-Cart-Sales-Rule-with-negated-condition-over-special-price-does - fix unit test --- .../Plugin/SalesRule/Model/Rule/Condition/ProductTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php index b1fc09e9676a2..54b7b71dd5ed8 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php @@ -219,10 +219,6 @@ public function testChildIsNotUsedForValidation() ->method('getProduct') ->willReturn($simpleProductMock); - $item->expects($this->once()) - ->method('setProduct') - ->with($this->identicalTo($simpleProductMock)); - $this->validator->setAttribute('special_price'); $this->validatorPlugin->beforeValidate($this->validator, $item);