From 5a0ede662d78f1f74a6cff1ae972a1b7c4e5fdf6 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Sat, 22 Jan 2022 15:04:55 +0530 Subject: [PATCH 01/31] Product's price is not correct inside wishlist when custom option is selected --- .../Pricing/ConfiguredPrice/ConfigurableProduct.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index 7a16b83eaf51d..b67cd526a1a12 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -57,8 +57,10 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\ */ public function getValue() { - $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); - + $price = $this->getProduct()->getMinimalPrice(); + if(!$price) { + $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); + } return max(0, $price); } From 24726c0b2340e21dd100965ef3f2670a873cf783 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 24 Jan 2022 18:17:17 +0530 Subject: [PATCH 02/31] changes for automation tests --- .../ConfiguredPrice/ConfigurableProduct.php | 5 +++-- .../ConfigurableProductTest.php | 20 +++++-------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index b67cd526a1a12..e4c002d3b6844 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -17,7 +17,7 @@ class ConfigurableProduct extends AbstractPrice /** * Price type final. */ - const PRICE_CODE = 'final_price'; + public const PRICE_CODE = 'final_price'; /** * @var ItemInterface @@ -57,8 +57,9 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\ */ public function getValue() { + $price = $this->getProduct()->getMinimalPrice(); - if(!$price) { + if (!$price) { $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); } return max(0, $price); diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index e3780a7af0572..32211682eb902 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -55,6 +55,7 @@ protected function setUp(): void ->setMethods([ 'getPriceInfo', 'getCustomOption', + 'getMinimalPrice' ]) ->getMockForAbstractClass(); @@ -100,11 +101,11 @@ public function testGetValue() $wishlistItemOptionMock = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() ->getMock(); - $wishlistItemOptionMock->expects($this->once()) + $wishlistItemOptionMock->expects($this->atLeastOnce()) ->method('getProduct') ->willReturn($productMock); - $this->saleableItem->expects($this->once()) + $this->saleableItem->expects($this->atLeastOnce()) ->method('getCustomOption') ->with('simple_product') ->willReturn($wishlistItemOptionMock); @@ -116,25 +117,14 @@ public function testGetValueWithNoCustomOption() { $priceValue = 100; - $priceMock = $this->getMockBuilder(PriceInterface::class) - ->getMockForAbstractClass(); - $priceMock->expects($this->once()) - ->method('getValue') - ->willReturn($priceValue); - $this->saleableItem->expects($this->once()) ->method('getCustomOption') ->with('simple_product') ->willReturn(null); $this->saleableItem->expects($this->once()) - ->method('getPriceInfo') - ->willReturn($this->priceInfoMock); - - $this->priceInfoMock->expects($this->once()) - ->method('getPrice') - ->with(ConfigurableProduct::PRICE_CODE) - ->willReturn($priceMock); + ->method('getMinimalPrice') + ->willReturn(100); $this->assertEquals(100, $this->model->getValue()); } From 54b43ecb73ae97a0a1ffc2e8709f22125eb6b21d Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 24 Jan 2022 19:21:41 +0530 Subject: [PATCH 03/31] static tests changes --- .../Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index 32211682eb902..d89a550a364ac 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -124,7 +124,7 @@ public function testGetValueWithNoCustomOption() $this->saleableItem->expects($this->once()) ->method('getMinimalPrice') - ->willReturn(100); + ->willReturn($priceValue); $this->assertEquals(100, $this->model->getValue()); } From 1721f95fe04c7d44f440f5ab65a5570fc7bef267 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Tue, 25 Jan 2022 18:13:18 +0530 Subject: [PATCH 04/31] implementation change by picking up customizable options data from catalog options --- .../ConfiguredPrice/ConfigurableProduct.php | 15 +++++++---- .../ConfigurableProductTest.php | 25 +++++++++++++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index e4c002d3b6844..be5867bba5232 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -17,7 +17,7 @@ class ConfigurableProduct extends AbstractPrice /** * Price type final. */ - public const PRICE_CODE = 'final_price'; + const PRICE_CODE = 'final_price'; /** * @var ItemInterface @@ -57,11 +57,16 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\ */ public function getValue() { - - $price = $this->getProduct()->getMinimalPrice(); - if (!$price) { - $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); + $product = $this->getProduct(); + $price = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); + if ($product->getProductOptionsCollection()) { + foreach ($product->getProductOptionsCollection() as $configurableOptions) { + foreach ($configurableOptions->getValues() as $configurableOptionData) { + $price += $configurableOptionData->getData('price'); + } + } } + return max(0, $price); } diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index d89a550a364ac..e3a84f2eb2c60 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -55,7 +55,7 @@ protected function setUp(): void ->setMethods([ 'getPriceInfo', 'getCustomOption', - 'getMinimalPrice' + 'getProductOptionsCollection' ]) ->getMockForAbstractClass(); @@ -101,11 +101,11 @@ public function testGetValue() $wishlistItemOptionMock = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() ->getMock(); - $wishlistItemOptionMock->expects($this->atLeastOnce()) + $wishlistItemOptionMock->expects($this->once()) ->method('getProduct') ->willReturn($productMock); - $this->saleableItem->expects($this->atLeastOnce()) + $this->saleableItem->expects($this->once()) ->method('getCustomOption') ->with('simple_product') ->willReturn($wishlistItemOptionMock); @@ -117,14 +117,29 @@ public function testGetValueWithNoCustomOption() { $priceValue = 100; + $priceMock = $this->getMockBuilder(PriceInterface::class) + ->getMockForAbstractClass(); + $priceMock->expects($this->once()) + ->method('getValue') + ->willReturn($priceValue); + $this->saleableItem->expects($this->once()) ->method('getCustomOption') ->with('simple_product') ->willReturn(null); $this->saleableItem->expects($this->once()) - ->method('getMinimalPrice') - ->willReturn($priceValue); + ->method('getProductOptionsCollection') + ->willReturn(null); + + $this->saleableItem->expects($this->once()) + ->method('getPriceInfo') + ->willReturn($this->priceInfoMock); + + $this->priceInfoMock->expects($this->once()) + ->method('getPrice') + ->with(ConfigurableProduct::PRICE_CODE) + ->willReturn($priceMock); $this->assertEquals(100, $this->model->getValue()); } From 46ad64c8fc9621c80ded2f697063d36e421677c2 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Tue, 25 Jan 2022 18:54:22 +0530 Subject: [PATCH 05/31] static tests changes --- .../Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index be5867bba5232..b87bc7c2da4c8 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -17,7 +17,7 @@ class ConfigurableProduct extends AbstractPrice /** * Price type final. */ - const PRICE_CODE = 'final_price'; + public const PRICE_CODE = 'final_price'; /** * @var ItemInterface From bf0d1e9843bd1cde8ff256522357e8f3ef905fcd Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 31 Jan 2022 10:45:51 +0530 Subject: [PATCH 06/31] Unit Test Code coverage --- .../ConfiguredPrice/ConfigurableProduct.php | 8 +- .../ConfigurableProductTest.php | 81 +++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index b87bc7c2da4c8..b7b615a7bbc84 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -59,10 +59,12 @@ public function getValue() { $product = $this->getProduct(); $price = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); + if ($product->getProductOptionsCollection()) { - foreach ($product->getProductOptionsCollection() as $configurableOptions) { - foreach ($configurableOptions->getValues() as $configurableOptionData) { - $price += $configurableOptionData->getData('price'); + foreach ($product->getProductOptionsCollection() as $configurationOptionsVal) { + $configurableOptionsData = $configurationOptionsVal->getValues(); + foreach($configurableOptionsData as $configurableOptionData) { + $price += $configurableOptionData->getPrice(); } } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index e3a84f2eb2c60..3c55d3d03d1d2 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -7,6 +7,7 @@ namespace Magento\Wishlist\Test\Unit\Pricing\ConfiguredPrice; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; use Magento\Framework\Pricing\Adjustment\CalculatorInterface; use Magento\Framework\Pricing\Price\PriceInterface; @@ -46,6 +47,11 @@ class ConfigurableProductTest extends TestCase */ private $priceInfoMock; + /** + * @var ProductInterface|MockObject + */ + private $productCustomOption; + protected function setUp(): void { $this->priceInfoMock = $this->getMockBuilder(PriceInfoInterface::class) @@ -65,6 +71,9 @@ protected function setUp(): void $this->priceCurrency = $this->getMockBuilder(PriceCurrencyInterface::class) ->getMockForAbstractClass(); + $this->productCustomOption = $this->getMockBuilder(ProductInterface::class) + ->getMockForAbstractClass(); + $this->model = new ConfigurableProduct( $this->saleableItem, null, @@ -143,4 +152,76 @@ public function testGetValueWithNoCustomOption() $this->assertEquals(100, $this->model->getValue()); } + + public function testGetValueWithCustomOption() { + $priceValue = 10; + $customOptionPrice = 5; + + $priceMock = $this->getMockBuilder(PriceInterface::class) + ->getMockForAbstractClass(); + + $priceMock->expects($this->once()) + ->method('getValue') + ->willReturn($priceValue); + + $this->priceInfoMock = $this->getMockBuilder(Base::class) + ->disableOriginalConstructor() + ->getMock(); + $this->priceInfoMock->expects($this->once()) + ->method('getPrice') + ->with(ConfigurableProduct::PRICE_CODE) + ->willReturn($priceMock); + + $productMock = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->getMock(); + $productMock->expects($this->once()) + ->method('getPriceInfo') + ->willReturn($this->priceInfoMock); + + $wishlistItemOptionMock = $this->getMockBuilder(Option::class) + ->disableOriginalConstructor() + ->getMock(); + $wishlistItemOptionMock->expects($this->once()) + ->method('getProduct') + ->willReturn($productMock); + + $this->saleableItem->expects($this->once()) + ->method('getCustomOption') + ->with('simple_product') + ->willReturn($wishlistItemOptionMock); + + $productOptionMock = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Option\Collection') + ->disableOriginalConstructor() + ->addMethods(['getValues']) + ->onlyMethods(['getIterator','getData']) + ->getMock(); + + $productValMock = $this->getMockBuilder('Magento\Catalog\Model\Product\Option\Value') + ->disableOriginalConstructor() + ->addMethods(['getIterator']) + ->onlyMethods(['getPrice']) + ->getMock(); + + $productMock->expects($this->atLeastOnce()) + ->method('getProductOptionsCollection') + ->willReturn($productOptionMock); + + $productOptionMock->expects($this->any())->method('getIterator') + ->willReturn(new \ArrayIterator([$productOptionMock])); + + $productOptionMock->expects($this->any()) + ->method('getValues') + ->willReturn($productValMock); + + $productValMock->expects($this->any())->method('getIterator') + ->willReturn(new \ArrayIterator([$productValMock])); + + $productValMock->expects($this->any()) + ->method('getPrice') + ->willReturn($customOptionPrice); + + $totalPrice = $priceValue + $customOptionPrice; + $this->assertEquals($totalPrice, $this->model->getValue()); + } } From 978c11a82e2bec4d9dcaa10fea336c485223ee37 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 31 Jan 2022 18:44:31 +0530 Subject: [PATCH 07/31] Unit Test Code coverage with test failure fixes --- .../Pricing/ConfiguredPrice/ConfigurableProduct.php | 4 ++-- .../ConfiguredPrice/ConfigurableProductTest.php | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index b7b615a7bbc84..b47e4ac6612c1 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -61,9 +61,9 @@ public function getValue() $price = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); if ($product->getProductOptionsCollection()) { - foreach ($product->getProductOptionsCollection() as $configurationOptionsVal) { + foreach ($product->getProductOptionsCollection() as $k => $configurationOptionsVal) { $configurableOptionsData = $configurationOptionsVal->getValues(); - foreach($configurableOptionsData as $configurableOptionData) { + foreach ($configurableOptionsData as $configurableOptionData) { $price += $configurableOptionData->getPrice(); } } diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index 3c55d3d03d1d2..c17e7bc179ccd 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -103,6 +103,7 @@ public function testGetValue() $productMock = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->getMock(); + $productMock->expects($this->once()) ->method('getPriceInfo') ->willReturn($this->priceInfoMock); @@ -153,7 +154,8 @@ public function testGetValueWithNoCustomOption() $this->assertEquals(100, $this->model->getValue()); } - public function testGetValueWithCustomOption() { + public function testGetValueWithCustomOption() + { $priceValue = 10; $customOptionPrice = 5; @@ -194,13 +196,13 @@ public function testGetValueWithCustomOption() { $productOptionMock = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Option\Collection') ->disableOriginalConstructor() ->addMethods(['getValues']) - ->onlyMethods(['getIterator','getData']) + ->onlyMethods(['getIterator']) ->getMock(); - $productValMock = $this->getMockBuilder('Magento\Catalog\Model\Product\Option\Value') + $productValMock = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection') ->disableOriginalConstructor() - ->addMethods(['getIterator']) - ->onlyMethods(['getPrice']) + ->addMethods(['getPrice']) + ->onlyMethods(['getIterator']) ->getMock(); $productMock->expects($this->atLeastOnce()) From 59359702a95602fa1ddaa5420770bb03dcdcec67 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 31 Jan 2022 19:23:13 +0530 Subject: [PATCH 08/31] unit test refactor --- .../ConfigurableProductTest.php | 62 +++++++++++-------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index c17e7bc179ccd..d1e87fa2ea055 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -19,6 +19,8 @@ use Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Magento\Catalog\Model\ResourceModel\Product\Option\Collection as optionCollection; +use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection as optionValueCollection; class ConfigurableProductTest extends TestCase { @@ -52,6 +54,16 @@ class ConfigurableProductTest extends TestCase */ private $productCustomOption; + /** + * @var optionCollection|MockObject + */ + private $productOptionMock; + + /** + * @var optionValueCollection|MockObject + */ + private $productValMock; + protected function setUp(): void { $this->priceInfoMock = $this->getMockBuilder(PriceInfoInterface::class) @@ -74,6 +86,18 @@ protected function setUp(): void $this->productCustomOption = $this->getMockBuilder(ProductInterface::class) ->getMockForAbstractClass(); + $this->productOptionMock = $this->getMockBuilder(optionCollection::class) + ->disableOriginalConstructor() + ->addMethods(['getValues']) + ->onlyMethods(['getIterator']) + ->getMock(); + + $this->productValMock = $this->getMockBuilder(optionValueCollection::class) + ->disableOriginalConstructor() + ->addMethods(['getPrice']) + ->onlyMethods(['getIterator']) + ->getMock(); + $this->model = new ConfigurableProduct( $this->saleableItem, null, @@ -180,6 +204,9 @@ public function testGetValueWithCustomOption() $productMock->expects($this->once()) ->method('getPriceInfo') ->willReturn($this->priceInfoMock); + $productMock->expects($this->atLeastOnce()) + ->method('getProductOptionsCollection') + ->willReturn($this->productOptionMock); $wishlistItemOptionMock = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() @@ -193,37 +220,18 @@ public function testGetValueWithCustomOption() ->with('simple_product') ->willReturn($wishlistItemOptionMock); - $productOptionMock = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Option\Collection') - ->disableOriginalConstructor() - ->addMethods(['getValues']) - ->onlyMethods(['getIterator']) - ->getMock(); - - $productValMock = $this->getMockBuilder('Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection') - ->disableOriginalConstructor() - ->addMethods(['getPrice']) - ->onlyMethods(['getIterator']) - ->getMock(); - - $productMock->expects($this->atLeastOnce()) - ->method('getProductOptionsCollection') - ->willReturn($productOptionMock); - - $productOptionMock->expects($this->any())->method('getIterator') - ->willReturn(new \ArrayIterator([$productOptionMock])); - - $productOptionMock->expects($this->any()) + $this->productOptionMock->expects($this->any())->method('getIterator') + ->willReturn(new \ArrayIterator([$this->productOptionMock])); + $this->productOptionMock->expects($this->any()) ->method('getValues') - ->willReturn($productValMock); - - $productValMock->expects($this->any())->method('getIterator') - ->willReturn(new \ArrayIterator([$productValMock])); + ->willReturn($this->productValMock); - $productValMock->expects($this->any()) + $this->productValMock->expects($this->any())->method('getIterator') + ->willReturn(new \ArrayIterator([$this->productValMock])); + $this->productValMock->expects($this->any()) ->method('getPrice') ->willReturn($customOptionPrice); - $totalPrice = $priceValue + $customOptionPrice; - $this->assertEquals($totalPrice, $this->model->getValue()); + $this->assertEquals($priceValue + $customOptionPrice, $this->model->getValue()); } } From 0c0bdf86c7869e19afb5378d19ef787462b89257 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 31 Jan 2022 19:25:18 +0530 Subject: [PATCH 09/31] static tests changes --- .../Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index b47e4ac6612c1..66e8a4b17728e 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -61,7 +61,7 @@ public function getValue() $price = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); if ($product->getProductOptionsCollection()) { - foreach ($product->getProductOptionsCollection() as $k => $configurationOptionsVal) { + foreach ($product->getProductOptionsCollection() as $configurationOptionsVal) { $configurableOptionsData = $configurationOptionsVal->getValues(); foreach ($configurableOptionsData as $configurableOptionData) { $price += $configurableOptionData->getPrice(); From 05e9aaa57ad188fc04677013291b7a79cda14cea Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 31 Jan 2022 20:18:07 +0530 Subject: [PATCH 10/31] static tests changes --- .../Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index d1e87fa2ea055..301de0f3d97b3 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -22,6 +22,10 @@ use Magento\Catalog\Model\ResourceModel\Product\Option\Collection as optionCollection; use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection as optionValueCollection; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ + class ConfigurableProductTest extends TestCase { /** From 20d9e772780c5fb4f6e2f49cd2b80ab5be449f5d Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Tue, 15 Feb 2022 18:02:51 +0530 Subject: [PATCH 11/31] ACP2E-30: JSON code displayed for Recently view widget fixed --- .../View/Element/UiComponent/Context.php | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php index 72fb6dbbc7e37..3fd58a2ad24d0 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php @@ -349,13 +349,16 @@ protected function setAcceptType() { $this->acceptType = 'html'; - $rawAcceptType = $this->request->getHeader('Accept'); - if (strpos($rawAcceptType, 'json') !== false) { - $this->acceptType = 'json'; - } elseif (strpos($rawAcceptType, 'html') !== false) { - $this->acceptType = 'html'; - } elseif (strpos($rawAcceptType, 'xml') !== false) { - $this->acceptType = 'xml'; + $AcceptTypes = $this->getSortedAcceptHeader(); + foreach ($AcceptTypes as $key => $value) { + if (strpos($key, 'json') !== false) { + $this->acceptType = 'json'; + } elseif (strpos($key, 'html') !== false) { + $this->acceptType = 'html'; + } elseif (strpos($key, 'xml') !== false) { + $this->acceptType = 'xml'; + } + break; } } @@ -408,4 +411,27 @@ public function getUiComponentFactory() { return $this->uiComponentFactory; } + + /** + * Returns sorted accept header based on q value + * + * @return array + */ + private function getSortedAcceptHeader() + { + $AcceptTypes = []; + $rawAcceptType = $this->request->getHeader('Accept'); + $accept = explode(',', $rawAcceptType); + foreach ($accept as $a) { + // the default quality is 1. + $q = 1; + // check if there is a different quality + if (strpos($a, ';q=') !== false) { + list($a, $q) = explode(';q=', $a); + } + $AcceptTypes[$a] = $q; + } + arsort($AcceptTypes); + return $AcceptTypes; + } } From abe6afa14a7b20c1044fb3d409f18278816b33f7 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Tue, 15 Feb 2022 19:55:58 +0530 Subject: [PATCH 12/31] Static tests fix --- .../Magento/Framework/View/Element/UiComponent/Context.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php index 3fd58a2ad24d0..0480be6ca00bd 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php @@ -350,7 +350,7 @@ protected function setAcceptType() $this->acceptType = 'html'; $AcceptTypes = $this->getSortedAcceptHeader(); - foreach ($AcceptTypes as $key => $value) { + foreach (array_keys($AcceptTypes) as $key) { if (strpos($key, 'json') !== false) { $this->acceptType = 'json'; } elseif (strpos($key, 'html') !== false) { From f9143f0f6e11751f985b28a252b320bdbede39c9 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Wed, 16 Feb 2022 15:01:03 +0530 Subject: [PATCH 13/31] Suggested changes implmented --- .../View/Element/UiComponent/Context.php | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php index 0480be6ca00bd..8557e9a99c425 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php @@ -349,13 +349,13 @@ protected function setAcceptType() { $this->acceptType = 'html'; - $AcceptTypes = $this->getSortedAcceptHeader(); - foreach (array_keys($AcceptTypes) as $key) { - if (strpos($key, 'json') !== false) { + $acceptTypes = $this->getSortedAcceptHeader(); + foreach ($acceptTypes as $acceptType) { + if (strpos($acceptType, 'json') !== false) { $this->acceptType = 'json'; - } elseif (strpos($key, 'html') !== false) { + } elseif (strpos($acceptType, 'html') !== false) { $this->acceptType = 'html'; - } elseif (strpos($key, 'xml') !== false) { + } elseif (strpos($acceptType, 'xml') !== false) { $this->acceptType = 'xml'; } break; @@ -419,19 +419,24 @@ public function getUiComponentFactory() */ private function getSortedAcceptHeader() { - $AcceptTypes = []; - $rawAcceptType = $this->request->getHeader('Accept'); - $accept = explode(',', $rawAcceptType); - foreach ($accept as $a) { + $acceptTypes = []; + $acceptHeader = $this->request->getHeader('Accept'); + $contentTypes = explode(',', $acceptHeader); + foreach ($contentTypes as $contentType) { // the default quality is 1. $q = 1; // check if there is a different quality - if (strpos($a, ';q=') !== false) { - list($a, $q) = explode(';q=', $a); + if (strpos($contentType, ';q=') !== false) { + list($contentType, $q) = explode(';q=', $contentType); + } + + if (array_key_exists($q, $acceptTypes)) { + $acceptTypes[$q] = $acceptTypes[$q] . ',' . $contentType; + } else { + $acceptTypes[$q] = $contentType; } - $AcceptTypes[$a] = $q; } - arsort($AcceptTypes); - return $AcceptTypes; + krsort($acceptTypes); + return array_values($acceptTypes); } } From 7a3c79f8f40e24746a45cb3210f8e214a1bf6814 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Thu, 17 Feb 2022 17:05:44 +0530 Subject: [PATCH 14/31] Added Unit Test for UIComponent Context file --- .../Unit/Element/UiComponent/ContextTest.php | 118 +++++++++++++++--- 1 file changed, 103 insertions(+), 15 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php index f7c6fcdf6f230..5dee2a9c33190 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php @@ -45,36 +45,71 @@ class ContextTest extends TestCase */ private $authorization; + /** + * @var LayoutInterface + */ + private $pageLayout; + + /** + * @var ButtonProviderFactory + */ + private $buttonProviderFactory; + + /** + * @var ActionPoolFactory + */ + private $actionPoolFactory; + + /** + * @var ContentTypeFactory + */ + private $contentTypeFactory; + + /** + * @var UrlInterface + */ + private $urlBuilder; + + /** + * @var Processor + */ + private $processor; + + /** + * @var UiComponentFactory + */ + private $uiComponentFactory; + protected function setUp(): void { - $pageLayout = $this->getMockBuilder(LayoutInterface::class) + $this->pageLayout = $this->getMockBuilder(LayoutInterface::class) ->getMock(); $request = $this->getMockBuilder(Http::class) ->disableOriginalConstructor() ->onlyMethods(['getHeader']) ->getMock(); $request->method('getHeader')->willReturn(''); - $buttonProviderFactory = + $this->buttonProviderFactory = $this->getMockBuilder(ButtonProviderFactory::class) ->disableOriginalConstructor() ->getMock(); - $actionPoolFactory = + $this->actionPoolFactory = $this->getMockBuilder(ActionPoolFactory::class) ->disableOriginalConstructor() ->getMock(); $this->actionPool = $this->getMockBuilder(ActionPoolInterface::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $actionPoolFactory->method('create')->willReturn($this->actionPool); - $contentTypeFactory = + $this->actionPoolFactory->method('create')->willReturn($this->actionPool); + $this->contentTypeFactory = $this->getMockBuilder(ContentTypeFactory::class) ->disableOriginalConstructor() ->getMock(); - $urlBuilder = $this->getMockBuilder(UrlInterface::class) + $this->urlBuilder = $this->getMockBuilder(UrlInterface::class) ->getMock(); - $processor = $this->getMockBuilder(Processor::class) + $this->processor = $this->getMockBuilder(Processor::class) ->getMock(); - $uiComponentFactory = + $this->uiComponentFactory = $this->getMockBuilder(UiComponentFactory::class) ->disableOriginalConstructor() ->getMock(); @@ -86,14 +121,14 @@ protected function setUp(): void $this->context = $objectManagerHelper->getObject( Context::class, [ - 'pageLayout' => $pageLayout, + 'pageLayout' => $this->pageLayout, 'request' => $request, - 'buttonProviderFactory' => $buttonProviderFactory, - 'actionPoolFactory' => $actionPoolFactory, - 'contentTypeFactory' => $contentTypeFactory, - 'urlBuilder' => $urlBuilder, - 'processor' => $processor, - 'uiComponentFactory' => $uiComponentFactory, + 'buttonProviderFactory' => $this->buttonProviderFactory, + 'actionPoolFactory' => $this->actionPoolFactory, + 'contentTypeFactory' => $this->contentTypeFactory, + 'urlBuilder' => $this->urlBuilder, + 'processor' => $this->processor, + 'uiComponentFactory' => $this->uiComponentFactory, 'authorization' => $this->authorization, ] ); @@ -162,6 +197,59 @@ public function testAddComponentDefinition($components, $expected) $this->assertEquals($expected, $this->context->getComponentsDefinitions()); } + /** + * @param string $headerAccept + * @param string $acceptType + * + * @dataProvider getAcceptTypeDataProvider + */ + public function testGetAcceptType($headerAccept, $acceptType) + { + $request = $this->getMockBuilder(Http::class) + ->disableOriginalConstructor() + ->onlyMethods(['getHeader']) + ->getMock(); + $request->method('getHeader') + ->with('Accept') + ->willReturn($headerAccept); + + $objectManagerHelper = new ObjectManagerHelper($this); + $context = $objectManagerHelper->getObject( + Context::class, + [ + 'pageLayout' => $this->pageLayout, + 'request' => $request, + 'buttonProviderFactory' => $this->buttonProviderFactory, + 'actionPoolFactory' => $this->actionPoolFactory, + 'contentTypeFactory' => $this->contentTypeFactory, + 'urlBuilder' => $this->urlBuilder, + 'processor' => $this->processor, + 'uiComponentFactory' => $this->uiComponentFactory, + 'authorization' => $this->authorization, + ] + ); + + $this->assertEquals($acceptType, $context->getAcceptType()); + } + + /** + * @return array + */ + public function getAcceptTypeDataProvider() + { + return [ + ['json', 'json'], + ['text/html,application/xhtml+xml,application/json;q=0.9, + application/javascript;q=0.9,text/javascript;q=0.9,application/xml;q=0.9, + text/plain;q=0.8,*/*;q=0.7', 'html'], + ['application/json, text/javascript, */*;q=0.01', 'json'], + ['text/html, application/xhtml+xml, application/xml;q=0.9, + image/avif, image/webp, image/apng, */*;q=0.8, + application/signed-exchange;v=b3;q=0.9', 'html'], + ['xml', 'xml'] + ]; + } + /** * @return array */ From 9bde49fdf55d613c9c3eacabbf53b2b19dca2df8 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Fri, 18 Feb 2022 10:10:41 +0530 Subject: [PATCH 15/31] Suggested test changes added --- .../View/Test/Unit/Element/UiComponent/ContextTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php index 5dee2a9c33190..7fce88ec4a8ad 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/UiComponent/ContextTest.php @@ -246,7 +246,8 @@ public function getAcceptTypeDataProvider() ['text/html, application/xhtml+xml, application/xml;q=0.9, image/avif, image/webp, image/apng, */*;q=0.8, application/signed-exchange;v=b3;q=0.9', 'html'], - ['xml', 'xml'] + ['xml', 'xml'], + ['text/html, application/json', 'json'] ]; } From 4e4eeb7aed5934eaed8cc03aafc2c1c6056accd7 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Tue, 22 Feb 2022 16:30:19 +0530 Subject: [PATCH 16/31] ACP2E-295: Product swatch base image thumb js issue fixes --- .../Magento/Swatches/view/base/web/js/swatch-renderer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js index 6782a87b02a9f..6f2c88852ae52 100644 --- a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js @@ -1248,9 +1248,10 @@ define([ */ _setImageType: function (images) { var initial = this.options.mediaGalleryInitial[0].img; + var mediaGalleryInitial = this.options.mediaGalleryInitial; - if (images[0].img === initial) { - images = $.extend(true, [], this.options.mediaGalleryInitial); + if (images[0].img === initial && (images.length === mediaGalleryInitial.length)) { + images = $.extend(true, [], mediaGalleryInitial); } else { images.map(function (img) { if (!img.type) { From 5d8a3acc1428d7bae50f4f0322851aa1dbafea25 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 21 Feb 2022 20:04:49 +0530 Subject: [PATCH 17/31] Product's price is not correct inside wishlist --- .../Helper/Catalog/Product/Configuration.php | 151 ++++++++++++++++++ .../Helper/Product/Configuration/Plugin.php | 4 + .../Observer/InitOptionRendererObserver.php | 29 ++++ .../Magento/ConfigurableProduct/etc/di.xml | 2 +- .../ConfigurableProduct/etc/frontend/di.xml | 7 + .../etc/frontend/events.xml | 12 ++ .../Block/Customer/Wishlist/Item/Options.php | 3 + .../ConfiguredPrice/ConfigurableProduct.php | 14 +- .../ConfigurableProductTest.php | 100 ------------ 9 files changed, 209 insertions(+), 113 deletions(-) create mode 100644 app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php create mode 100644 app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php create mode 100644 app/code/Magento/ConfigurableProduct/etc/frontend/events.xml diff --git a/app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php b/app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php new file mode 100644 index 0000000000000..2ea4e553f67ec --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php @@ -0,0 +1,151 @@ +productConfiguration = $productConfiguration; + $this->pricingHelper = $pricingHelper; + $this->escaper = $escaper; + $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Serialize\Serializer\Json::class); + parent::__construct($context); + } + + /** + * Custom options with price value + * + * @param ItemInterface $item + * @return array|bool|float|int|string|null + * @throws \Magento\Framework\Exception\LocalizedException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getCustomOptions(ItemInterface $item) //phpcs:ignore Generic.Metrics.NestingLevel + { + $product = $item->getProduct(); + $options = []; + $optionIds = $item->getOptionByCode('option_ids'); + if ($optionIds && $optionIds->getValue()) { + $options = []; + foreach (explode(',', $optionIds->getValue()) as $optionId) { + $option = $product->getOptionById($optionId); + if ($option) { + $itemOption = $item->getOptionByCode('option_' . $option->getId()); + /** @var $group \Magento\Catalog\Model\Product\Option\Type\DefaultType */ + $group = $option->groupFactory($option->getType()) + ->setOption($option) + ->setConfigurationItem($item) + ->setConfigurationItemOption($itemOption); + $priceInfo = $product->getPriceInfo(); + $basePrice = $priceInfo->getPrice('final_price')->getAmount()->getValue(); + + if ('file' == $option->getType()) { + $downloadParams = $item->getFileDownloadParams(); + if ($downloadParams) { + $url = $downloadParams->getUrl(); + if ($url) { + $group->setCustomOptionDownloadUrl($url); + } + $urlParams = $downloadParams->getUrlParams(); + if ($urlParams) { + $group->setCustomOptionUrlParams($urlParams); + } + } + } + + $optionData = [ + 'label' => $option->getTitle(), + 'value' => $group->getFormattedOptionValue($itemOption->getValue()), + 'print_value' => $group->getPrintableOptionValue($itemOption->getValue()), + 'option_id' => $option->getId(), + 'option_type' => $option->getType(), + 'custom_view' => $group->isCustomizedView(), + ]; + + if ($group->getOptionPrice($itemOption->getValue(), $basePrice) !== null) { + $optionData['price'] = $this->pricingHelper->currency( + $group->getOptionPrice($itemOption->getValue(), $basePrice) + ); + $optionData['has_html'] = true; + } + + if ($optionData) { + $options[] = $optionData; + } + + } + } + } + + $addOptions = $item->getOptionByCode('additional_options'); + if ($addOptions) { + $options = array_merge($options, $this->serializer->unserialize($addOptions->getValue())); + } + + return $options; + } + + /** + * Retrieves product options list + * + * @param ItemInterface $item + * @return array + */ + public function getOptions(ItemInterface $item) + { + $product = $item->getProduct(); + $attributes = $product->getTypeInstance()->getSelectedAttributesInfo($product); + return array_merge($attributes, $this->getCustomOptions($item)); + } +} diff --git a/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php b/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php index f2e062236b4d5..fd10fbd3258a8 100644 --- a/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php +++ b/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php @@ -6,6 +6,10 @@ */ namespace Magento\ConfigurableProduct\Helper\Product\Configuration; +/** + * @deprecated + * @see Magento\ConfigurableProduct\Helper\Catalog\Product\Configuration + */ class Plugin { /** diff --git a/app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php b/app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php new file mode 100644 index 0000000000000..edb4179c9db2b --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php @@ -0,0 +1,29 @@ +getBlock(); + $block->addOptionsRenderCfg('configurable', Configuration::class); + return $this; + } +} diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index 270e8ec746097..08bad2531aa87 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -30,7 +30,7 @@ - + diff --git a/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml b/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml index 56418bbaad122..af5e0c49e7798 100644 --- a/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml @@ -7,6 +7,13 @@ --> + + + + Magento\ConfigurableProduct\Helper\Catalog\Product\Configuration + + + diff --git a/app/code/Magento/ConfigurableProduct/etc/frontend/events.xml b/app/code/Magento/ConfigurableProduct/etc/frontend/events.xml new file mode 100644 index 0000000000000..686f74882bd82 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/etc/frontend/events.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php index 82133927e1201..431f6421946ef 100644 --- a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php +++ b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php @@ -118,6 +118,9 @@ public function getConfiguredOptions() } } $options[$index]['value'] = $option['value']; + if (array_key_exists('price', $option)) { + $options[$index]['value'] = $option['value'] .' '. $option['price']; + } } } diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index 66e8a4b17728e..7a16b83eaf51d 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -17,7 +17,7 @@ class ConfigurableProduct extends AbstractPrice /** * Price type final. */ - public const PRICE_CODE = 'final_price'; + const PRICE_CODE = 'final_price'; /** * @var ItemInterface @@ -57,17 +57,7 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\ */ public function getValue() { - $product = $this->getProduct(); - $price = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); - - if ($product->getProductOptionsCollection()) { - foreach ($product->getProductOptionsCollection() as $configurationOptionsVal) { - $configurableOptionsData = $configurationOptionsVal->getValues(); - foreach ($configurableOptionsData as $configurableOptionData) { - $price += $configurableOptionData->getPrice(); - } - } - } + $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); return max(0, $price); } diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index 301de0f3d97b3..e3780a7af0572 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -7,7 +7,6 @@ namespace Magento\Wishlist\Test\Unit\Pricing\ConfiguredPrice; -use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; use Magento\Framework\Pricing\Adjustment\CalculatorInterface; use Magento\Framework\Pricing\Price\PriceInterface; @@ -19,12 +18,6 @@ use Magento\Wishlist\Pricing\ConfiguredPrice\ConfigurableProduct; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Magento\Catalog\Model\ResourceModel\Product\Option\Collection as optionCollection; -use Magento\Catalog\Model\ResourceModel\Product\Option\Value\Collection as optionValueCollection; - -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ class ConfigurableProductTest extends TestCase { @@ -53,21 +46,6 @@ class ConfigurableProductTest extends TestCase */ private $priceInfoMock; - /** - * @var ProductInterface|MockObject - */ - private $productCustomOption; - - /** - * @var optionCollection|MockObject - */ - private $productOptionMock; - - /** - * @var optionValueCollection|MockObject - */ - private $productValMock; - protected function setUp(): void { $this->priceInfoMock = $this->getMockBuilder(PriceInfoInterface::class) @@ -77,7 +55,6 @@ protected function setUp(): void ->setMethods([ 'getPriceInfo', 'getCustomOption', - 'getProductOptionsCollection' ]) ->getMockForAbstractClass(); @@ -87,21 +64,6 @@ protected function setUp(): void $this->priceCurrency = $this->getMockBuilder(PriceCurrencyInterface::class) ->getMockForAbstractClass(); - $this->productCustomOption = $this->getMockBuilder(ProductInterface::class) - ->getMockForAbstractClass(); - - $this->productOptionMock = $this->getMockBuilder(optionCollection::class) - ->disableOriginalConstructor() - ->addMethods(['getValues']) - ->onlyMethods(['getIterator']) - ->getMock(); - - $this->productValMock = $this->getMockBuilder(optionValueCollection::class) - ->disableOriginalConstructor() - ->addMethods(['getPrice']) - ->onlyMethods(['getIterator']) - ->getMock(); - $this->model = new ConfigurableProduct( $this->saleableItem, null, @@ -131,7 +93,6 @@ public function testGetValue() $productMock = $this->getMockBuilder(Product::class) ->disableOriginalConstructor() ->getMock(); - $productMock->expects($this->once()) ->method('getPriceInfo') ->willReturn($this->priceInfoMock); @@ -166,10 +127,6 @@ public function testGetValueWithNoCustomOption() ->with('simple_product') ->willReturn(null); - $this->saleableItem->expects($this->once()) - ->method('getProductOptionsCollection') - ->willReturn(null); - $this->saleableItem->expects($this->once()) ->method('getPriceInfo') ->willReturn($this->priceInfoMock); @@ -181,61 +138,4 @@ public function testGetValueWithNoCustomOption() $this->assertEquals(100, $this->model->getValue()); } - - public function testGetValueWithCustomOption() - { - $priceValue = 10; - $customOptionPrice = 5; - - $priceMock = $this->getMockBuilder(PriceInterface::class) - ->getMockForAbstractClass(); - - $priceMock->expects($this->once()) - ->method('getValue') - ->willReturn($priceValue); - - $this->priceInfoMock = $this->getMockBuilder(Base::class) - ->disableOriginalConstructor() - ->getMock(); - $this->priceInfoMock->expects($this->once()) - ->method('getPrice') - ->with(ConfigurableProduct::PRICE_CODE) - ->willReturn($priceMock); - - $productMock = $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->getMock(); - $productMock->expects($this->once()) - ->method('getPriceInfo') - ->willReturn($this->priceInfoMock); - $productMock->expects($this->atLeastOnce()) - ->method('getProductOptionsCollection') - ->willReturn($this->productOptionMock); - - $wishlistItemOptionMock = $this->getMockBuilder(Option::class) - ->disableOriginalConstructor() - ->getMock(); - $wishlistItemOptionMock->expects($this->once()) - ->method('getProduct') - ->willReturn($productMock); - - $this->saleableItem->expects($this->once()) - ->method('getCustomOption') - ->with('simple_product') - ->willReturn($wishlistItemOptionMock); - - $this->productOptionMock->expects($this->any())->method('getIterator') - ->willReturn(new \ArrayIterator([$this->productOptionMock])); - $this->productOptionMock->expects($this->any()) - ->method('getValues') - ->willReturn($this->productValMock); - - $this->productValMock->expects($this->any())->method('getIterator') - ->willReturn(new \ArrayIterator([$this->productValMock])); - $this->productValMock->expects($this->any()) - ->method('getPrice') - ->willReturn($customOptionPrice); - - $this->assertEquals($priceValue + $customOptionPrice, $this->model->getValue()); - } } From e58898bbee4dd39395a1e68b2101a58347e02ea9 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Wed, 23 Feb 2022 12:44:10 +0530 Subject: [PATCH 18/31] Static test fixes --- .../Magento/Swatches/view/base/web/js/swatch-renderer.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js index 6f2c88852ae52..be1e4699b0c5f 100644 --- a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js @@ -1248,10 +1248,9 @@ define([ */ _setImageType: function (images) { var initial = this.options.mediaGalleryInitial[0].img; - var mediaGalleryInitial = this.options.mediaGalleryInitial; - if (images[0].img === initial && (images.length === mediaGalleryInitial.length)) { - images = $.extend(true, [], mediaGalleryInitial); + if (images[0].img === initial && images.length === this.options.mediaGalleryInitial.length) { + images = $.extend(true, [], this.options.mediaGalleryInitial); } else { images.map(function (img) { if (!img.type) { From 64070c8249305f90ce7c1b168334ea23fa04b777 Mon Sep 17 00:00:00 2001 From: glo5363 Date: Thu, 24 Feb 2022 16:56:47 +0530 Subject: [PATCH 19/31] Product's price is not correct inside wishlist reimplementation --- .../Helper/Catalog/Product/Configuration.php | 151 ------------------ .../Helper/Product/Configuration/Plugin.php | 4 - .../Observer/InitOptionRendererObserver.php | 29 ---- .../Magento/ConfigurableProduct/etc/di.xml | 2 +- .../ConfigurableProduct/etc/frontend/di.xml | 7 - .../etc/frontend/events.xml | 12 -- .../Block/Customer/Wishlist/Item/Options.php | 3 - .../ConfiguredPrice/ConfigurableProduct.php | 28 +++- 8 files changed, 27 insertions(+), 209 deletions(-) delete mode 100644 app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php delete mode 100644 app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php delete mode 100644 app/code/Magento/ConfigurableProduct/etc/frontend/events.xml diff --git a/app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php b/app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php deleted file mode 100644 index 2ea4e553f67ec..0000000000000 --- a/app/code/Magento/ConfigurableProduct/Helper/Catalog/Product/Configuration.php +++ /dev/null @@ -1,151 +0,0 @@ -productConfiguration = $productConfiguration; - $this->pricingHelper = $pricingHelper; - $this->escaper = $escaper; - $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\Serialize\Serializer\Json::class); - parent::__construct($context); - } - - /** - * Custom options with price value - * - * @param ItemInterface $item - * @return array|bool|float|int|string|null - * @throws \Magento\Framework\Exception\LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function getCustomOptions(ItemInterface $item) //phpcs:ignore Generic.Metrics.NestingLevel - { - $product = $item->getProduct(); - $options = []; - $optionIds = $item->getOptionByCode('option_ids'); - if ($optionIds && $optionIds->getValue()) { - $options = []; - foreach (explode(',', $optionIds->getValue()) as $optionId) { - $option = $product->getOptionById($optionId); - if ($option) { - $itemOption = $item->getOptionByCode('option_' . $option->getId()); - /** @var $group \Magento\Catalog\Model\Product\Option\Type\DefaultType */ - $group = $option->groupFactory($option->getType()) - ->setOption($option) - ->setConfigurationItem($item) - ->setConfigurationItemOption($itemOption); - $priceInfo = $product->getPriceInfo(); - $basePrice = $priceInfo->getPrice('final_price')->getAmount()->getValue(); - - if ('file' == $option->getType()) { - $downloadParams = $item->getFileDownloadParams(); - if ($downloadParams) { - $url = $downloadParams->getUrl(); - if ($url) { - $group->setCustomOptionDownloadUrl($url); - } - $urlParams = $downloadParams->getUrlParams(); - if ($urlParams) { - $group->setCustomOptionUrlParams($urlParams); - } - } - } - - $optionData = [ - 'label' => $option->getTitle(), - 'value' => $group->getFormattedOptionValue($itemOption->getValue()), - 'print_value' => $group->getPrintableOptionValue($itemOption->getValue()), - 'option_id' => $option->getId(), - 'option_type' => $option->getType(), - 'custom_view' => $group->isCustomizedView(), - ]; - - if ($group->getOptionPrice($itemOption->getValue(), $basePrice) !== null) { - $optionData['price'] = $this->pricingHelper->currency( - $group->getOptionPrice($itemOption->getValue(), $basePrice) - ); - $optionData['has_html'] = true; - } - - if ($optionData) { - $options[] = $optionData; - } - - } - } - } - - $addOptions = $item->getOptionByCode('additional_options'); - if ($addOptions) { - $options = array_merge($options, $this->serializer->unserialize($addOptions->getValue())); - } - - return $options; - } - - /** - * Retrieves product options list - * - * @param ItemInterface $item - * @return array - */ - public function getOptions(ItemInterface $item) - { - $product = $item->getProduct(); - $attributes = $product->getTypeInstance()->getSelectedAttributesInfo($product); - return array_merge($attributes, $this->getCustomOptions($item)); - } -} diff --git a/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php b/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php index fd10fbd3258a8..f2e062236b4d5 100644 --- a/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php +++ b/app/code/Magento/ConfigurableProduct/Helper/Product/Configuration/Plugin.php @@ -6,10 +6,6 @@ */ namespace Magento\ConfigurableProduct\Helper\Product\Configuration; -/** - * @deprecated - * @see Magento\ConfigurableProduct\Helper\Catalog\Product\Configuration - */ class Plugin { /** diff --git a/app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php b/app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php deleted file mode 100644 index edb4179c9db2b..0000000000000 --- a/app/code/Magento/ConfigurableProduct/Observer/InitOptionRendererObserver.php +++ /dev/null @@ -1,29 +0,0 @@ -getBlock(); - $block->addOptionsRenderCfg('configurable', Configuration::class); - return $this; - } -} diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index 08bad2531aa87..270e8ec746097 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -30,7 +30,7 @@ - + diff --git a/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml b/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml index af5e0c49e7798..56418bbaad122 100644 --- a/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/frontend/di.xml @@ -7,13 +7,6 @@ --> - - - - Magento\ConfigurableProduct\Helper\Catalog\Product\Configuration - - - diff --git a/app/code/Magento/ConfigurableProduct/etc/frontend/events.xml b/app/code/Magento/ConfigurableProduct/etc/frontend/events.xml deleted file mode 100644 index 686f74882bd82..0000000000000 --- a/app/code/Magento/ConfigurableProduct/etc/frontend/events.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php index 431f6421946ef..82133927e1201 100644 --- a/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php +++ b/app/code/Magento/Wishlist/Block/Customer/Wishlist/Item/Options.php @@ -118,9 +118,6 @@ public function getConfiguredOptions() } } $options[$index]['value'] = $option['value']; - if (array_key_exists('price', $option)) { - $options[$index]['value'] = $option['value'] .' '. $option['price']; - } } } diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index 7a16b83eaf51d..dbe077110b5bd 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -17,7 +17,7 @@ class ConfigurableProduct extends AbstractPrice /** * Price type final. */ - const PRICE_CODE = 'final_price'; + public const PRICE_CODE = 'final_price'; /** * @var ItemInterface @@ -57,8 +57,31 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\ */ public function getValue() { + /** @var \Magento\Catalog\Model\Product $configurableProduct */ + $configurableProduct = parent::getProduct(); + + /** @var \Magento\Wishlist\Model\Item\Option $configurableCustomOption */ + $configurableCustomOption = $configurableProduct->getCustomOption('option_ids'); + $customPrice = 0; + if ($configurableCustomOption) { + $item = $this->item; + foreach (explode(',', $configurableCustomOption->getValue()) as $optionId) { + $option = $configurableProduct->getOptionById($optionId); + if ($option) { + $itemOption = $item->getOptionByCode('option_' . $option->getId()); + /** @var $group \Magento\Catalog\Model\Product\Option\Type\DefaultType */ + $group = $option->groupFactory($option->getType()) + ->setOption($option) + ->setConfigurationItemOption($itemOption); + $basePrice = $configurableProduct->getPriceInfo()->getPrice('final_price')->getAmount()->getValue(); + $customPrice += $group->getOptionPrice($itemOption->getValue(), $basePrice); + } + } + } $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); - + if ($customPrice) { + $price = $price + $customPrice; + } return max(0, $price); } @@ -78,6 +101,7 @@ public function getProduct() { /** @var \Magento\Catalog\Model\Product $product */ $product = parent::getProduct(); + /** @var \Magento\Wishlist\Model\Item\Option $customOption */ $customOption = $product->getCustomOption('simple_product'); From 0111e09ce806fc281a1c1a44c16d3cf08275bf4b Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Mon, 28 Feb 2022 18:52:41 +0530 Subject: [PATCH 20/31] ACP2E-295: Added additional check for image validation --- app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js index be1e4699b0c5f..f6b5b2ee9853e 100644 --- a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js @@ -1249,7 +1249,7 @@ define([ _setImageType: function (images) { var initial = this.options.mediaGalleryInitial[0].img; - if (images[0].img === initial && images.length === this.options.mediaGalleryInitial.length) { + if (images[0].img === initial && images.length === 1) { images = $.extend(true, [], this.options.mediaGalleryInitial); } else { images.map(function (img) { From 98b055e250cef9f3d1ce50615fbf9ff662dadcde Mon Sep 17 00:00:00 2001 From: glo5363 Date: Mon, 28 Feb 2022 17:36:35 +0530 Subject: [PATCH 21/31] covered with unit test --- .../ConfiguredPrice/ConfigurableProduct.php | 18 ++- .../ConfigurableProductTest.php | 118 ++++++++++++++++-- 2 files changed, 116 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php index dbe077110b5bd..37859ab1f4e75 100644 --- a/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php +++ b/app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php @@ -57,28 +57,26 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\ */ public function getValue() { - /** @var \Magento\Catalog\Model\Product $configurableProduct */ - $configurableProduct = parent::getProduct(); - + $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); + /** @var \Magento\Catalog\Model\Product $product */ + $product = parent::getProduct(); /** @var \Magento\Wishlist\Model\Item\Option $configurableCustomOption */ - $configurableCustomOption = $configurableProduct->getCustomOption('option_ids'); + $configurableCustomOption = $product->getCustomOption('option_ids'); $customPrice = 0; - if ($configurableCustomOption) { + if ($configurableCustomOption && $configurableCustomOption->getValue()) { $item = $this->item; + $configurableProduct = $configurableCustomOption->getProduct(); foreach (explode(',', $configurableCustomOption->getValue()) as $optionId) { $option = $configurableProduct->getOptionById($optionId); if ($option) { $itemOption = $item->getOptionByCode('option_' . $option->getId()); /** @var $group \Magento\Catalog\Model\Product\Option\Type\DefaultType */ $group = $option->groupFactory($option->getType()) - ->setOption($option) - ->setConfigurationItemOption($itemOption); - $basePrice = $configurableProduct->getPriceInfo()->getPrice('final_price')->getAmount()->getValue(); - $customPrice += $group->getOptionPrice($itemOption->getValue(), $basePrice); + ->setOption($option); + $customPrice += $group->getOptionPrice($itemOption->getValue(), $price); } } } - $price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue(); if ($customPrice) { $price = $price + $customPrice; } diff --git a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php index e3780a7af0572..dad8751648c19 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php @@ -8,6 +8,10 @@ namespace Magento\Wishlist\Test\Unit\Pricing\ConfiguredPrice; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface; +use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface; +use Magento\Catalog\Model\Product\Option\Type\DefaultType; +use Magento\Catalog\Model\Product\Option as ProductOption; use Magento\Framework\Pricing\Adjustment\CalculatorInterface; use Magento\Framework\Pricing\Price\PriceInterface; use Magento\Framework\Pricing\PriceCurrencyInterface; @@ -19,6 +23,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class ConfigurableProductTest extends TestCase { /** @@ -72,9 +79,16 @@ protected function setUp(): void ); } - public function testGetValue() + /** + * @param array $options + * + * @dataProvider setOptionsDataProvider + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function testGetValue(array $options, $optionIds) { $priceValue = 10; + $customPrice = 100; $priceMock = $this->getMockBuilder(PriceInterface::class) ->getMockForAbstractClass(); @@ -100,14 +114,66 @@ public function testGetValue() $wishlistItemOptionMock = $this->getMockBuilder(Option::class) ->disableOriginalConstructor() ->getMock(); - $wishlistItemOptionMock->expects($this->once()) - ->method('getProduct') - ->willReturn($productMock); + $wishlistItemOptionMock->expects($this->exactly(2)) + ->method('getProduct')->willReturn($productMock); - $this->saleableItem->expects($this->once()) + $this->saleableItem->expects($this->any()) ->method('getCustomOption') - ->with('simple_product') - ->willReturn($wishlistItemOptionMock); + ->withConsecutive(['simple_product'], ['option_ids']) + ->willReturnOnConsecutiveCalls($wishlistItemOptionMock, $wishlistItemOptionMock); + + $wishlistItemOptionMock->expects($this->any()) + ->method('getValue')->willReturn($optionIds); + + $wishlistItemOptionMock->expects($this->exactly(2)) + ->method('getProduct')->willReturn($productMock); + + $productOptionMock = $this->getMockBuilder(ProductOption::class) + ->disableOriginalConstructor() + ->getMock(); + + $defaultTypeMock = $this->getMockBuilder(DefaultType::class) + ->disableOriginalConstructor() + ->getMock(); + + $productOptionMock->expects($this->any()) + ->method('getId') + ->willReturn($options['option_id']); + $productOptionMock->expects($this->any()) + ->method('getType') + ->willReturn($options['type']); + + $productOptionMock->expects($this->any()) + ->method('groupFactory') + ->with($options['type']) + ->willReturn($defaultTypeMock); + $productMock->expects($this->any()) + ->method('getOptionById') + ->with($options['option_id'])->willReturn($productOptionMock); + $defaultTypeMock->expects($this->any()) + ->method('setOption') + ->with($productOptionMock) + ->willReturnSelf(); + + $itemMock = $this->getMockForAbstractClass(ItemInterface::class); + $this->model->setItem($itemMock); + + $optionInterfaceMock = $this->getMockForAbstractClass(OptionInterface::class); + + $itemMock->expects($this->any()) + ->method('getOptionByCode') + ->with('option_'.$options['option_id']) + ->willReturn($optionInterfaceMock); + + $optionInterfaceMock->expects($this->any()) + ->method('getValue') + ->willReturn($productOptionMock); + + $defaultTypeMock->expects($this->any()) + ->method('getOptionPrice') + ->with($productOptionMock, $priceValue) + ->willReturn($customPrice); + $priceValue += $customPrice; $this->assertEquals($priceValue, $this->model->getValue()); } @@ -122,10 +188,10 @@ public function testGetValueWithNoCustomOption() ->method('getValue') ->willReturn($priceValue); - $this->saleableItem->expects($this->once()) + $this->saleableItem->expects($this->any()) ->method('getCustomOption') - ->with('simple_product') - ->willReturn(null); + ->withConsecutive(['simple_product'], ['option_ids']) + ->willReturnOnConsecutiveCalls(null, null); $this->saleableItem->expects($this->once()) ->method('getPriceInfo') @@ -138,4 +204,36 @@ public function testGetValueWithNoCustomOption() $this->assertEquals(100, $this->model->getValue()); } + + public function setOptionsDataProvider(): array + { + return ['options' => + [ + [ + 'option_id' => '1', + 'product_id' => '2091', + 'type' => 'checkbox', + 'is_require' => '1', + 'default_title' => 'check', + 'title' => 'check', + 'default_price' => null, + 'default_price_type' => null, + 'price' => null, + 'price_type' => null + ], '1', + [ + 'option_id' => '2', + 'product_id' => '2091', + 'type' => 'field', + 'is_require' => '1', + 'default_title' => 'field', + 'title' => 'field', + 'default_price' => '100.000000', + 'default_price_type' => 'fixed', + 'price' => '100.000000', + 'price_type' => 'fixed' + ], '2' + ], + ]; + } } From 19c17f50de0c1efae0184f7af37ff47245e9d1e3 Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Mon, 28 Feb 2022 22:09:17 +0530 Subject: [PATCH 22/31] ACP2E-295: Removed the condition from swatch-rendered.js file --- .../Swatches/view/base/web/js/swatch-renderer.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js index f6b5b2ee9853e..0fb819aee4c9d 100644 --- a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js @@ -1247,17 +1247,12 @@ define([ * @param {Array} images */ _setImageType: function (images) { - var initial = this.options.mediaGalleryInitial[0].img; - if (images[0].img === initial && images.length === 1) { - images = $.extend(true, [], this.options.mediaGalleryInitial); - } else { - images.map(function (img) { - if (!img.type) { - img.type = 'image'; - } - }); - } + images.map(function (img) { + if (!img.type) { + img.type = 'image'; + } + }); return images; }, From ae4eee556fd1f48391bc80641cdb183ea603b5bd Mon Sep 17 00:00:00 2001 From: Nishant Rana Date: Fri, 4 Mar 2022 12:01:36 +0530 Subject: [PATCH 23/31] Added MFTF Test coverage for the js issue fix --- ...SwatchToConfigurableProductActionGroup.xml | 49 ++++++++ ...igurableOptionsImportSameBaseImageTest.xml | 112 ++++++++++++++++++ ...mport_configurable_product_same_images.csv | 5 + 3 files changed, 166 insertions(+) create mode 100644 app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml create mode 100644 app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml create mode 100644 dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv diff --git a/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml new file mode 100644 index 0000000000000..9696b9a2a277c --- /dev/null +++ b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml @@ -0,0 +1,49 @@ + + + + + + + Add text swatch property attribute. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml new file mode 100644 index 0000000000000..c2a0a34a7120e --- /dev/null +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml @@ -0,0 +1,112 @@ + + + + + + + + + + <description value="Login as admin, create attribute with three options, configurable product with three + associated simple products. Add few images for products, check the fotorama thumbnail images + (visible and active) for each selected option for the configurable product"/> + <severity value="MAJOR"/> + <group value="swatches"/> + </annotations> + <before> + <!-- Login as Admin --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> + + <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="createDirectory" stepKey="createDirectoryForImportImages"> + <argument name="path">var/import/images/{{ImportProduct_Configurable.name}}</argument> + </helper> + <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="copy" stepKey="copyBaseImage"> + <argument name="source">dev/tests/acceptance/tests/_data/{{ImportProductSimple3_Configurable.baseImage}}</argument> + <argument name="destination">var/import/images/{{ImportProduct_Configurable.name}}/{{ImportProductSimple3_Configurable.baseImage}}</argument> + </helper> + <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="copy" stepKey="copyProduct1BaseImage"> + <argument name="source">dev/tests/acceptance/tests/_data/{{ImportProductSimple2_Configurable.baseImage}}</argument> + <argument name="destination">var/import/images/{{ImportProduct_Configurable.name}}/{{ImportProductSimple2_Configurable.baseImage}}</argument> + </helper> + <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="copy" stepKey="copyProduct2BaseImage"> + <argument name="source">dev/tests/acceptance/tests/_data/{{ImportProductSimple1_Configurable.baseImage}}</argument> + <argument name="destination">var/import/images/{{ImportProduct_Configurable.name}}/{{ImportProductSimple1_Configurable.baseImage}}</argument> + </helper> + </before> + <after> + <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteAttribute"> + <argument name="productAttributeLabel" value="Set Size" /> + </actionGroup> + <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="deleteDirectory" stepKey="deleteProductImageDirectory"> + <argument name="path">var/import/images/{{ImportProduct_Configurable.name}}</argument> + </helper> + <!-- Logout --> + <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <magentoCron groups="index" stepKey="reindexInvalidatedIndices"/> + </after> + <!--Create text swatch attribute with 3 options: Small, Medium and Large--> + <actionGroup ref="AddTextSwatchToConfigurableProductActionGroup" stepKey="addSizeAttribute"> + <argument name="attributeName" value="Set Size"/> + <argument name="attributeCode" value="set_size"/> + <argument name="4" value="4"/> + <argument name="24" value="24"/> + <argument name="30" value="30"/> + </actionGroup> + <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="amOnAttributeSetPage"/> + <click selector="{{AdminProductAttributeSetGridSection.AttributeSetName('Default')}}" stepKey="chooseDefaultAttributeSet"/> + <waitForPageLoad stepKey="waitForAttributeSetPageLoad"/> + <dragAndDrop selector1="{{UnassignedAttributes.ProductAttributeName('set_size')}}" selector2="{{Group.FolderName('Product Details')}}" stepKey="moveProductAttributeToGroup"/> + <click selector="{{AttributeSetSection.Save}}" stepKey="saveAttributeSet"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear" /> + + <actionGroup ref="AdminImportProductsWithCustomImagesDirectoryActionGroup" stepKey="adminImportProduct"> + <argument name="behavior" value="Add/Update"/> + <argument name="importFile" value="import_configurable_product_same_images.csv"/> + <argument name="imagesFileDirectory" value="{{ImportProduct_Configurable.name}}"/> + </actionGroup> + + <!-- Reindex invalidated indices after product attribute has been created/deleted --> + <magentoCron groups="index" stepKey="reindexInvalidatedIndices"/> + <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches"> + <argument name="tags" value="config full_page"/> + </actionGroup> + + <!-- Open the configurable product page on storefront --> + <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> + <argument name="productUrlKey" value="{{ImportProduct_Configurable.name}}"/> + </actionGroup> + <!-- Select first option --> + <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectFirstOptionValue"> + <argument name="optionName" value="4"/> + </actionGroup> + <seeElement selector="{{StorefrontProductMediaSection.productImageInFotorama(ImportProductSimple3_Configurable.baseImage)}}" stepKey="seeFirstImageInRibbon"/> + <!-- Select second option --> + <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectSecondOptionValue"> + <argument name="optionName" value="24"/> + </actionGroup> + <!-- Select third option --> + <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectThirdOptionValue"> + <argument name="optionName" value="30"/> + </actionGroup> + + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> + <argument name="sku" value="import-product-configurable"/> + </actionGroup> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct2"> + <argument name="sku" value="import-product-simple1-configurable"/> + </actionGroup> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct3"> + <argument name="sku" value="import-product-simple2-configurable"/> + </actionGroup> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct4"> + <argument name="sku" value="import-product-simple3-configurable"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv b/dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv new file mode 100644 index 0000000000000..d336d7279079f --- /dev/null +++ b/dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv @@ -0,0 +1,5 @@ +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,associated_skus,downloadable_links,downloadable_samples,configurable_variations,configurable_variation_labels +import-product-simple1-configurable,,Default,simple,,base,import-product-simple1-configurable,,,1,1,Taxable Goods,Search,11,,,,import-product-simple1-configurable,,,,magento-logo.png,Magento Logo,magento-logo.png,Magento Logo,magento-logo.png,Magento Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,set_size=24,101,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,"magento-logo.png,m-logo.gif,adobe-base.jpg",,,,,,,,,,,,,, +import-product-simple2-configurable,,Default,simple,,base,import-product-simple2-configurable,,,2,1,Taxable Goods,Search,12,,,,import-product-simple2-configurable,,,,m-logo.gif,M Logo,m-logo.gif,M Logo,m-logo.gif,M Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,set_size=30,102,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,"m-logo.gif,adobe-base.jpg,magento-logo.png",,,,,,,,,,,,,, +import-product-simple3-configurable,,Default,simple,,base,import-product-simple3-configurable,,,3,1,Taxable Goods,Search,13,,,,import-product-simple3-configurable,,,,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,set_size=4,103,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,"adobe-base.jpg,m-logo.gif,magento-logo.png",,,,,,,,,,,,,, +import-product-configurable,,Default,configurable,Default Category,base,import-product-configurable,,,,1,Taxable Goods,"Catalog, Search",,,,,import-product-configurable,,,,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,,,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,adobe-base.jpg,,,,,,,,,,,,,"sku=import-product-simple1-configurable,set_size=24|sku=import-product-simple2-configurable,set_size=30|sku=import-product-simple3-configurable,set_size=4",set_size=Set Size \ No newline at end of file From b6259da0158811e108b8199644cd3166ea85b1af Mon Sep 17 00:00:00 2001 From: Nishant Rana <glo04412@adobe.com> Date: Fri, 4 Mar 2022 12:28:12 +0530 Subject: [PATCH 24/31] MFTF Static Check fixes --- .../StorefrontConfigurableOptionsImportSameBaseImageTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml index c2a0a34a7120e..85198c258b30e 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml @@ -11,8 +11,8 @@ <test name="StorefrontConfigurableOptionsImportSameBaseImageTest"> <annotations> <features value="Swatches"/> - <stories value="Configurable product with swatch attribute"/> - <title value="Check thumbnail images and active image for Configurable Product with swatch attribute"/> + <stories value="Configurable product import same base image"/> + <title value="Check thumbnail images for Configurable Product with same base image from Import option"/> <description value="Login as admin, create attribute with three options, configurable product with three associated simple products. Add few images for products, check the fotorama thumbnail images (visible and active) for each selected option for the configurable product"/> From f163b17c961fd5007e732378debca6ebc65f1d31 Mon Sep 17 00:00:00 2001 From: abhattGlo <glo36217@adobe.com> Date: Wed, 2 Mar 2022 13:56:25 +0530 Subject: [PATCH 25/31] ACP2E-231:Fixed Preview does not show sale prices created through catalog price rules --- .../Search/ViewModel/SearchQueryParams.php | 26 +++++++++++++++++++ .../Search/view/frontend/layout/default.xml | 1 + .../view/frontend/templates/form.mini.phtml | 8 ++++++ .../CatalogSearch/Block/ResultTest.php | 12 ++++++++- 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Search/ViewModel/SearchQueryParams.php diff --git a/app/code/Magento/Search/ViewModel/SearchQueryParams.php b/app/code/Magento/Search/ViewModel/SearchQueryParams.php new file mode 100644 index 0000000000000..b4caa5db56953 --- /dev/null +++ b/app/code/Magento/Search/ViewModel/SearchQueryParams.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Search\ViewModel; + +use Magento\Framework\View\Element\Block\ArgumentInterface; + +/** + * View model for search query params + */ +class SearchQueryParams implements ArgumentInterface +{ + /** + * Return search query params + * + * @return array + */ + public function getSearchQueryParams(): array + { + return []; + } +} diff --git a/app/code/Magento/Search/view/frontend/layout/default.xml b/app/code/Magento/Search/view/frontend/layout/default.xml index 69c99f979d51b..19c8efbfa2f59 100644 --- a/app/code/Magento/Search/view/frontend/layout/default.xml +++ b/app/code/Magento/Search/view/frontend/layout/default.xml @@ -11,6 +11,7 @@ <block class="Magento\Framework\View\Element\Template" name="top.search" as="topSearch" template="Magento_Search::form.mini.phtml"> <arguments> <argument name="configProvider" xsi:type="object">Magento\Search\ViewModel\ConfigProvider</argument> + <argument name="searchQueryParams" xsi:type="object">Magento\Search\ViewModel\SearchQueryParams</argument> </arguments> </block> </referenceContainer> diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index c6b2a6a729575..a7a770195c6e2 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -10,6 +10,8 @@ /** @var $escaper \Magento\Framework\Escaper */ /** @var $configProvider \Magento\Search\ViewModel\ConfigProvider */ $configProvider = $block->getData('configProvider'); +/** @var $versionManager \Magento\Search\ViewModel\SearchQueryParams */ +$searchParams = $block->getData('searchQueryParams'); /** @var $helper \Magento\Search\Helper\Data */ $helper = $configProvider->getSearchHelperData(); $allowedSuggestion = $configProvider->isSuggestionsAllowed(); @@ -20,6 +22,12 @@ $quickSearchUrl = $allowedSuggestion ? $escaper->escapeUrl($helper->getSuggestUr <div class="block block-content"> <form class="form minisearch" id="search_mini_form" action="<?= $escaper->escapeUrl($helper->getResultUrl()) ?>" method="get"> + <?php if (!empty($queryParams = $searchParams->getSearchQueryParams())): ?> + <?php foreach ($queryParams as $param): ?> + <input type="hidden" name="<?= $escaper->escapeHtmlAttr($param['name']) ?>" + value="<?= $escaper->escapeHtmlAttr($param['value']) ?>"/> + <?php endforeach; ?> + <?php endif; ?> <div class="field search"> <label class="label" for="search" data-role="minisearch-label"> <span><?= $escaper->escapeHtml(__('Search')) ?></span> diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php index 6d679a5aea7d4..37d7a62816568 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php @@ -73,8 +73,18 @@ public function testEscapeSearchText(string $searchValue, string $expectedOutput /** @var Result $searchResultBlock */ $searchResultBlock = $this->layout->createBlock(Result::class); /** @var Template $searchBlock */ + $searchQueryParams = $this->getMockBuilder(\Magento\Search\ViewModel\SearchQueryParams::class) + ->disableOriginalConstructor() + ->setMethods(['getSearchQueryParams']) + ->getMock(); + $searchQueryParams->expects($this->any()) + ->method('getSearchQueryParams') + ->willReturn([]); $searchBlock = $this->layout->createBlock(Template::class); - $searchBlock->setData(['configProvider' => $this->configProvider]); + $searchBlock->setData([ + 'configProvider' => $this->configProvider, + 'searchQueryParams' => $searchQueryParams, + ]); $searchBlock->setTemplate('Magento_Search::form.mini.phtml'); /** @var RequestInterface $request */ $request = $this->objectManager->get(RequestInterface::class); From af3f1d13a3ae06a92295ddd6b63469e9a5e33064 Mon Sep 17 00:00:00 2001 From: Nishant Rana <glo04412@adobe.com> Date: Mon, 7 Mar 2022 15:58:53 +0530 Subject: [PATCH 26/31] ACP2E-533: Fixes for Product Videos playing from additional youtube script issue --- .../ProductVideo/view/frontend/web/js/load-player.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/code/Magento/ProductVideo/view/frontend/web/js/load-player.js b/app/code/Magento/ProductVideo/view/frontend/web/js/load-player.js index a37af596cc631..8fb1b8991d6f3 100644 --- a/app/code/Magento/ProductVideo/view/frontend/web/js/load-player.js +++ b/app/code/Magento/ProductVideo/view/frontend/web/js/load-player.js @@ -240,6 +240,14 @@ define([ return; } + + // if script already loaded by other library + if (window.YT) { + videoRegister.register('youtube', true); + $(window).trigger('youtubeapiready'); + + return; + } videoRegister.register('youtube'); element = document.createElement('script'); From af00291fe056adf52b6a374576251d11b720f409 Mon Sep 17 00:00:00 2001 From: abhattGlo <glo36217@adobe.com> Date: Mon, 7 Mar 2022 23:02:41 +0530 Subject: [PATCH 27/31] ACP2E-231:SearchQueryParams changed to SearchAdditionalFormData --- ...SearchQueryParams.php => SearchAdditionalFormData.php} | 6 +++--- app/code/Magento/Search/view/frontend/layout/default.xml | 2 +- .../Search/view/frontend/templates/form.mini.phtml | 6 +++--- .../testsuite/Magento/CatalogSearch/Block/ResultTest.php | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) rename app/code/Magento/Search/ViewModel/{SearchQueryParams.php => SearchAdditionalFormData.php} (70%) diff --git a/app/code/Magento/Search/ViewModel/SearchQueryParams.php b/app/code/Magento/Search/ViewModel/SearchAdditionalFormData.php similarity index 70% rename from app/code/Magento/Search/ViewModel/SearchQueryParams.php rename to app/code/Magento/Search/ViewModel/SearchAdditionalFormData.php index b4caa5db56953..918fe8b5366c8 100644 --- a/app/code/Magento/Search/ViewModel/SearchQueryParams.php +++ b/app/code/Magento/Search/ViewModel/SearchAdditionalFormData.php @@ -10,16 +10,16 @@ use Magento\Framework\View\Element\Block\ArgumentInterface; /** - * View model for search query params + * View model for search additional form params */ -class SearchQueryParams implements ArgumentInterface +class SearchAdditionalFormData implements ArgumentInterface { /** * Return search query params * * @return array */ - public function getSearchQueryParams(): array + public function getFormData(): array { return []; } diff --git a/app/code/Magento/Search/view/frontend/layout/default.xml b/app/code/Magento/Search/view/frontend/layout/default.xml index 19c8efbfa2f59..478fd338c4474 100644 --- a/app/code/Magento/Search/view/frontend/layout/default.xml +++ b/app/code/Magento/Search/view/frontend/layout/default.xml @@ -11,7 +11,7 @@ <block class="Magento\Framework\View\Element\Template" name="top.search" as="topSearch" template="Magento_Search::form.mini.phtml"> <arguments> <argument name="configProvider" xsi:type="object">Magento\Search\ViewModel\ConfigProvider</argument> - <argument name="searchQueryParams" xsi:type="object">Magento\Search\ViewModel\SearchQueryParams</argument> + <argument name="searchAdditionalFormData" xsi:type="object">Magento\Search\ViewModel\SearchAdditionalFormData</argument> </arguments> </block> </referenceContainer> diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index a7a770195c6e2..0ab42c2b938be 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -10,8 +10,8 @@ /** @var $escaper \Magento\Framework\Escaper */ /** @var $configProvider \Magento\Search\ViewModel\ConfigProvider */ $configProvider = $block->getData('configProvider'); -/** @var $versionManager \Magento\Search\ViewModel\SearchQueryParams */ -$searchParams = $block->getData('searchQueryParams'); +/** @var $versionManager \Magento\Search\ViewModel\SearchAdditionalFormData */ +$searchAdditionalFormParams = $block->getData('searchAdditionalFormData'); /** @var $helper \Magento\Search\Helper\Data */ $helper = $configProvider->getSearchHelperData(); $allowedSuggestion = $configProvider->isSuggestionsAllowed(); @@ -22,7 +22,7 @@ $quickSearchUrl = $allowedSuggestion ? $escaper->escapeUrl($helper->getSuggestUr <div class="block block-content"> <form class="form minisearch" id="search_mini_form" action="<?= $escaper->escapeUrl($helper->getResultUrl()) ?>" method="get"> - <?php if (!empty($queryParams = $searchParams->getSearchQueryParams())): ?> + <?php if (!empty($queryParams = $searchAdditionalFormParams->getFormData())): ?> <?php foreach ($queryParams as $param): ?> <input type="hidden" name="<?= $escaper->escapeHtmlAttr($param['name']) ?>" value="<?= $escaper->escapeHtmlAttr($param['value']) ?>"/> diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php index 37d7a62816568..d3d4d639d2a68 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php @@ -73,17 +73,17 @@ public function testEscapeSearchText(string $searchValue, string $expectedOutput /** @var Result $searchResultBlock */ $searchResultBlock = $this->layout->createBlock(Result::class); /** @var Template $searchBlock */ - $searchQueryParams = $this->getMockBuilder(\Magento\Search\ViewModel\SearchQueryParams::class) + $searchQueryParams = $this->getMockBuilder(\Magento\Search\ViewModel\SearchAdditionalFormData::class) ->disableOriginalConstructor() - ->setMethods(['getSearchQueryParams']) + ->setMethods(['getFormData']) ->getMock(); $searchQueryParams->expects($this->any()) - ->method('getSearchQueryParams') + ->method('getFormData') ->willReturn([]); $searchBlock = $this->layout->createBlock(Template::class); $searchBlock->setData([ 'configProvider' => $this->configProvider, - 'searchQueryParams' => $searchQueryParams, + 'searchAdditionalFormData' => $searchQueryParams, ]); $searchBlock->setTemplate('Magento_Search::form.mini.phtml'); /** @var RequestInterface $request */ From e1c6e62efa96fc8673ea34ac9b9ad8a1263fb28e Mon Sep 17 00:00:00 2001 From: abhattGlo <glo36217@adobe.com> Date: Mon, 7 Mar 2022 23:13:14 +0530 Subject: [PATCH 28/31] ACP2E-231:Code Review Fixes --- ...hAdditionalFormData.php => AdditionalSearchFormData.php} | 2 +- app/code/Magento/Search/view/frontend/layout/default.xml | 2 +- .../Magento/Search/view/frontend/templates/form.mini.phtml | 6 +++--- .../testsuite/Magento/CatalogSearch/Block/ResultTest.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename app/code/Magento/Search/ViewModel/{SearchAdditionalFormData.php => AdditionalSearchFormData.php} (87%) diff --git a/app/code/Magento/Search/ViewModel/SearchAdditionalFormData.php b/app/code/Magento/Search/ViewModel/AdditionalSearchFormData.php similarity index 87% rename from app/code/Magento/Search/ViewModel/SearchAdditionalFormData.php rename to app/code/Magento/Search/ViewModel/AdditionalSearchFormData.php index 918fe8b5366c8..84745a1eb04be 100644 --- a/app/code/Magento/Search/ViewModel/SearchAdditionalFormData.php +++ b/app/code/Magento/Search/ViewModel/AdditionalSearchFormData.php @@ -12,7 +12,7 @@ /** * View model for search additional form params */ -class SearchAdditionalFormData implements ArgumentInterface +class AdditionalSearchFormData implements ArgumentInterface { /** * Return search query params diff --git a/app/code/Magento/Search/view/frontend/layout/default.xml b/app/code/Magento/Search/view/frontend/layout/default.xml index 478fd338c4474..99675b98d4f0f 100644 --- a/app/code/Magento/Search/view/frontend/layout/default.xml +++ b/app/code/Magento/Search/view/frontend/layout/default.xml @@ -11,7 +11,7 @@ <block class="Magento\Framework\View\Element\Template" name="top.search" as="topSearch" template="Magento_Search::form.mini.phtml"> <arguments> <argument name="configProvider" xsi:type="object">Magento\Search\ViewModel\ConfigProvider</argument> - <argument name="searchAdditionalFormData" xsi:type="object">Magento\Search\ViewModel\SearchAdditionalFormData</argument> + <argument name="searchAdditionalFormData" xsi:type="object">Magento\Search\ViewModel\AdditionalSearchFormData</argument> </arguments> </block> </referenceContainer> diff --git a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml index 0ab42c2b938be..67aa709103ded 100644 --- a/app/code/Magento/Search/view/frontend/templates/form.mini.phtml +++ b/app/code/Magento/Search/view/frontend/templates/form.mini.phtml @@ -10,8 +10,8 @@ /** @var $escaper \Magento\Framework\Escaper */ /** @var $configProvider \Magento\Search\ViewModel\ConfigProvider */ $configProvider = $block->getData('configProvider'); -/** @var $versionManager \Magento\Search\ViewModel\SearchAdditionalFormData */ -$searchAdditionalFormParams = $block->getData('searchAdditionalFormData'); +/** @var $versionManager \Magento\Search\ViewModel\AdditionalSearchFormData */ +$additionalSearchFormData = $block->getData('additionalSearchFormData'); /** @var $helper \Magento\Search\Helper\Data */ $helper = $configProvider->getSearchHelperData(); $allowedSuggestion = $configProvider->isSuggestionsAllowed(); @@ -22,7 +22,7 @@ $quickSearchUrl = $allowedSuggestion ? $escaper->escapeUrl($helper->getSuggestUr <div class="block block-content"> <form class="form minisearch" id="search_mini_form" action="<?= $escaper->escapeUrl($helper->getResultUrl()) ?>" method="get"> - <?php if (!empty($queryParams = $searchAdditionalFormParams->getFormData())): ?> + <?php if (!empty($queryParams = $additionalSearchFormData->getFormData())): ?> <?php foreach ($queryParams as $param): ?> <input type="hidden" name="<?= $escaper->escapeHtmlAttr($param['name']) ?>" value="<?= $escaper->escapeHtmlAttr($param['value']) ?>"/> diff --git a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php index d3d4d639d2a68..3bdd89803c54c 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php @@ -73,7 +73,7 @@ public function testEscapeSearchText(string $searchValue, string $expectedOutput /** @var Result $searchResultBlock */ $searchResultBlock = $this->layout->createBlock(Result::class); /** @var Template $searchBlock */ - $searchQueryParams = $this->getMockBuilder(\Magento\Search\ViewModel\SearchAdditionalFormData::class) + $searchQueryParams = $this->getMockBuilder(\Magento\Search\ViewModel\AdditionalSearchFormData::class) ->disableOriginalConstructor() ->setMethods(['getFormData']) ->getMock(); @@ -83,7 +83,7 @@ public function testEscapeSearchText(string $searchValue, string $expectedOutput $searchBlock = $this->layout->createBlock(Template::class); $searchBlock->setData([ 'configProvider' => $this->configProvider, - 'searchAdditionalFormData' => $searchQueryParams, + 'additionalSearchFormData' => $searchQueryParams, ]); $searchBlock->setTemplate('Magento_Search::form.mini.phtml'); /** @var RequestInterface $request */ From 5b8355037a0538bf3e775087971ca54a6c097fdd Mon Sep 17 00:00:00 2001 From: abhattGlo <glo36217@adobe.com> Date: Mon, 7 Mar 2022 23:20:45 +0530 Subject: [PATCH 29/31] ACP2E-231:Changed argument name of viewModel --- app/code/Magento/Search/view/frontend/layout/default.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Search/view/frontend/layout/default.xml b/app/code/Magento/Search/view/frontend/layout/default.xml index 99675b98d4f0f..390de1883c886 100644 --- a/app/code/Magento/Search/view/frontend/layout/default.xml +++ b/app/code/Magento/Search/view/frontend/layout/default.xml @@ -11,7 +11,7 @@ <block class="Magento\Framework\View\Element\Template" name="top.search" as="topSearch" template="Magento_Search::form.mini.phtml"> <arguments> <argument name="configProvider" xsi:type="object">Magento\Search\ViewModel\ConfigProvider</argument> - <argument name="searchAdditionalFormData" xsi:type="object">Magento\Search\ViewModel\AdditionalSearchFormData</argument> + <argument name="additionalSearchFormData" xsi:type="object">Magento\Search\ViewModel\AdditionalSearchFormData</argument> </arguments> </block> </referenceContainer> From d46da951a0ff65d1d399c9a4863a86736ff057c9 Mon Sep 17 00:00:00 2001 From: Nishant Rana <glo04412@adobe.com> Date: Wed, 9 Mar 2022 12:44:35 +0530 Subject: [PATCH 30/31] Made CR suggested changes in mftf --- ...SwatchToConfigurableProductActionGroup.xml | 49 ----------- ...watchProductAttributeFrontendLabelData.xml | 4 + ...igurableOptionsImportSameBaseImageTest.xml | 81 ++++++++++--------- 3 files changed, 48 insertions(+), 86 deletions(-) delete mode 100644 app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml diff --git a/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml b/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml deleted file mode 100644 index 9696b9a2a277c..0000000000000 --- a/app/code/Magento/Swatches/Test/Mftf/ActionGroup/AddTextSwatchToConfigurableProductActionGroup.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AddTextSwatchToConfigurableProductActionGroup"> - <annotations> - <description>Add text swatch property attribute.</description> - </annotations> - <arguments> - <argument name="attributeName" defaultValue="{{textSwatchAttribute.default_label}}" type="string"/> - <argument name="attributeCode" defaultValue="{{textSwatchAttribute.attribute_code}}" type="string"/> - <argument name="4" defaultValue="4" type="string"/> - <argument name="24" defaultValue="24" type="string"/> - <argument name="30" defaultValue="30" type="string"/> - <argument name="usedInProductListing" defaultValue="No" type="string"/> - <argument name="usedInLayeredNavigation" defaultValue="No" type="string"/> - </arguments> - - <amOnPage url="{{ProductAttributePage.url}}" stepKey="goToNewProductAttributePage"/> - <waitForPageLoad stepKey="waitForNewProductAttributePage"/> - <fillField selector="{{AttributePropertiesSection.DefaultLabel}}" userInput="{{attributeName}}" stepKey="fillDefaultLabel"/> - <selectOption selector="{{AttributePropertiesSection.InputType}}" userInput="{{textSwatchAttribute.input_type}}" stepKey="selectInputType"/> - <selectOption selector="{{AttributePropertiesSection.UpdateProductPreviewImage}}" userInput="Yes" stepKey="setUpdateProductPreviewImage"/> - <click selector="{{AdminManageSwatchSection.addSwatchText}}" stepKey="clickAddSwatch1"/> - <fillField selector="{{AdminManageSwatchSection.swatchTextByIndex('0')}}" userInput="{{4}}" stepKey="fillSwatch1"/> - <fillField selector="{{AdminManageSwatchSection.swatchAdminDescriptionByIndex('0')}}" userInput="{{4}}" stepKey="fillSwatch1Description"/> - <click selector="{{AdminManageSwatchSection.addSwatchText}}" stepKey="clickAddSwatch2"/> - <fillField selector="{{AdminManageSwatchSection.swatchTextByIndex('1')}}" userInput="{{24}}" stepKey="fillSwatch2"/> - <fillField selector="{{AdminManageSwatchSection.swatchAdminDescriptionByIndex('1')}}" userInput="{{24}}" stepKey="fillSwatch2Description"/> - <click selector="{{AdminManageSwatchSection.addSwatchText}}" stepKey="clickAddSwatch3"/> - <fillField selector="{{AdminManageSwatchSection.swatchTextByIndex('2')}}" userInput="{{30}}" stepKey="fillSwatch3"/> - <fillField selector="{{AdminManageSwatchSection.swatchAdminDescriptionByIndex('2')}}" userInput="{{30}}" stepKey="fillSwatch3Description"/> - <click selector="{{AttributePropertiesSection.AdvancedProperties}}" stepKey="expandAdvancedProperties"/> - <selectOption selector="{{AttributePropertiesSection.Scope}}" userInput="1" stepKey="selectGlobalScope"/> - <fillField selector="{{AdvancedAttributePropertiesSection.AttributeCode}}" userInput="{{attributeCode}}" stepKey="fillAttributeCodeField"/> - <scrollToTopOfPage stepKey="scrollToTabs"/> - <click selector="{{StorefrontPropertiesSection.StoreFrontPropertiesTab}}" stepKey="clickStorefrontPropertiesTab"/> - <waitForElementVisible selector="{{AdvancedAttributePropertiesSection.UseInProductListing}}" stepKey="waitForTabSwitch"/> - <selectOption selector="{{AdvancedAttributePropertiesSection.UseInProductListing}}" userInput="{{usedInProductListing}}" stepKey="useInProductListing"/> - <selectOption selector="{{AttributePropertiesSection.useInLayeredNavigation}}" userInput="{{usedInLayeredNavigation}}" stepKey="useInLayeredNavigation"/> - <click selector="{{AttributePropertiesSection.SaveAndEdit}}" stepKey="clickSave"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml b/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml index 095fd65f3a99c..b5e42a4cd6992 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml @@ -12,4 +12,8 @@ <data key="store_id">0</data> <data key="label" unique="suffix">Swatch-Attribute-</data> </entity> + <entity name="SwatchProductSizeAttribute" type="FrontendLabel"> + <data key="frontend_label">Set Size</data> + <data key="attribute_code">set_size</data> + </entity> </entities> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml index 85198c258b30e..ca8d440e7db7c 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml @@ -40,43 +40,63 @@ </helper> </before> <after> - <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteAttribute"> - <argument name="productAttributeLabel" value="Set Size" /> - </actionGroup> <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="deleteDirectory" stepKey="deleteProductImageDirectory"> <argument name="path">var/import/images/{{ImportProduct_Configurable.name}}</argument> </helper> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> + <argument name="sku" value="import-product-configurable"/> + </actionGroup> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct2"> + <argument name="sku" value="import-product-simple1-configurable"/> + </actionGroup> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct3"> + <argument name="sku" value="import-product-simple2-configurable"/> + </actionGroup> + <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct4"> + <argument name="sku" value="import-product-simple3-configurable"/> + </actionGroup> + <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteAttribute"> + <argument name="productAttributeLabel" value="Set Size" /> + </actionGroup> <!-- Logout --> <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> - <!-- Reindex invalidated indices after product attribute has been created/deleted --> - <magentoCron groups="index" stepKey="reindexInvalidatedIndices"/> </after> - <!--Create text swatch attribute with 3 options: Small, Medium and Large--> - <actionGroup ref="AddTextSwatchToConfigurableProductActionGroup" stepKey="addSizeAttribute"> - <argument name="attributeName" value="Set Size"/> - <argument name="attributeCode" value="set_size"/> - <argument name="4" value="4"/> - <argument name="24" value="24"/> - <argument name="30" value="30"/> + <!--Create text swatch attribute with 3 options: 4, 24 and 30--> + <actionGroup ref="AddTextSwatchToProductActionGroup" stepKey="addSizeAttribute"> + <argument name="attributeName" value="{{SwatchProductSizeAttribute.frontend_label}}"/> + <argument name="attributeCode" value="{{SwatchProductSizeAttribute.attribute_code}}"/> + <argument name="option1" value="4"/> + <argument name="option2" value="24"/> + <argument name="option3" value="30"/> + </actionGroup> + + <!-- Go to created attribute (attribute page) --> + <actionGroup ref="NavigateToEditProductAttributeActionGroup" stepKey="navigateToSkuProductAttribute"> + <argument name="ProductAttribute" value="{{SwatchProductSizeAttribute.frontend_label}}"/> </actionGroup> - <amOnPage url="{{AdminProductAttributeSetGridPage.url}}" stepKey="amOnAttributeSetPage"/> - <click selector="{{AdminProductAttributeSetGridSection.AttributeSetName('Default')}}" stepKey="chooseDefaultAttributeSet"/> - <waitForPageLoad stepKey="waitForAttributeSetPageLoad"/> - <dragAndDrop selector1="{{UnassignedAttributes.ProductAttributeName('set_size')}}" selector2="{{Group.FolderName('Product Details')}}" stepKey="moveProductAttributeToGroup"/> - <click selector="{{AttributeSetSection.Save}}" stepKey="saveAttributeSet"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear" /> + <!-- Set 'yes' value for option "Update Product Preview Image" --> + <actionGroup ref="AdminUpdateProductPreviewImageActionGroup" stepKey="setUpdateProductPreviewImage" after="navigateToSkuProductAttribute"/> + <!-- Save Product Attribute --> + <actionGroup ref="SaveProductAttributeActionGroup" stepKey="saveAttribute" after="setUpdateProductPreviewImage"/> + + <actionGroup ref="AdminOpenAttributeSetGridPageActionGroup" stepKey="openAttributeSetPage"/> + + <!-- From grid, click on attribute set Default --> + <actionGroup ref="AdminOpenAttributeSetByNameActionGroup" stepKey="openDefaultAttributeSet"/> + + <!-- Add Product Attribute to Default attribute by dragging and dropping this to the 'Project Details' folder. Then Save. --> + <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignAttributeToGroup"> + <argument name="group" value="Product Details"/> + <argument name="attribute" value="{{SwatchProductSizeAttribute.attribute_code}}"/> + </actionGroup> + <actionGroup ref="SaveAttributeSetActionGroup" stepKey="saveAttributeSet"/> <actionGroup ref="AdminImportProductsWithCustomImagesDirectoryActionGroup" stepKey="adminImportProduct"> <argument name="behavior" value="Add/Update"/> <argument name="importFile" value="import_configurable_product_same_images.csv"/> <argument name="imagesFileDirectory" value="{{ImportProduct_Configurable.name}}"/> </actionGroup> - - <!-- Reindex invalidated indices after product attribute has been created/deleted --> - <magentoCron groups="index" stepKey="reindexInvalidatedIndices"/> - <actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches"> - <argument name="tags" value="config full_page"/> - </actionGroup> + <waitForPageLoad time="30" stepKey="waitForSaveImportProduct"/> <!-- Open the configurable product page on storefront --> <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> @@ -95,18 +115,5 @@ <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectThirdOptionValue"> <argument name="optionName" value="30"/> </actionGroup> - - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> - <argument name="sku" value="import-product-configurable"/> - </actionGroup> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct2"> - <argument name="sku" value="import-product-simple1-configurable"/> - </actionGroup> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct3"> - <argument name="sku" value="import-product-simple2-configurable"/> - </actionGroup> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct4"> - <argument name="sku" value="import-product-simple3-configurable"/> - </actionGroup> </test> </tests> From c3a7ad9985dbb30e497db55d36a23827aa32377c Mon Sep 17 00:00:00 2001 From: Nishant Rana <glo04412@adobe.com> Date: Tue, 22 Mar 2022 11:33:47 +0530 Subject: [PATCH 31/31] Revert ACP2E-295 changes --- ...watchProductAttributeFrontendLabelData.xml | 4 - ...igurableOptionsImportSameBaseImageTest.xml | 119 ------------------ .../view/base/web/js/swatch-renderer.js | 15 ++- ...mport_configurable_product_same_images.csv | 5 - 4 files changed, 10 insertions(+), 133 deletions(-) delete mode 100644 app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml delete mode 100644 dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv diff --git a/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml b/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml index b5e42a4cd6992..095fd65f3a99c 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Data/SwatchProductAttributeFrontendLabelData.xml @@ -12,8 +12,4 @@ <data key="store_id">0</data> <data key="label" unique="suffix">Swatch-Attribute-</data> </entity> - <entity name="SwatchProductSizeAttribute" type="FrontendLabel"> - <data key="frontend_label">Set Size</data> - <data key="attribute_code">set_size</data> - </entity> </entities> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml deleted file mode 100644 index ca8d440e7db7c..0000000000000 --- a/app/code/Magento/Swatches/Test/Mftf/Test/StorefrontConfigurableOptionsImportSameBaseImageTest.xml +++ /dev/null @@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="StorefrontConfigurableOptionsImportSameBaseImageTest"> - <annotations> - <features value="Swatches"/> - <stories value="Configurable product import same base image"/> - <title value="Check thumbnail images for Configurable Product with same base image from Import option"/> - <description value="Login as admin, create attribute with three options, configurable product with three - associated simple products. Add few images for products, check the fotorama thumbnail images - (visible and active) for each selected option for the configurable product"/> - <severity value="MAJOR"/> - <group value="swatches"/> - </annotations> - <before> - <!-- Login as Admin --> - <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin1"/> - - <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="createDirectory" stepKey="createDirectoryForImportImages"> - <argument name="path">var/import/images/{{ImportProduct_Configurable.name}}</argument> - </helper> - <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="copy" stepKey="copyBaseImage"> - <argument name="source">dev/tests/acceptance/tests/_data/{{ImportProductSimple3_Configurable.baseImage}}</argument> - <argument name="destination">var/import/images/{{ImportProduct_Configurable.name}}/{{ImportProductSimple3_Configurable.baseImage}}</argument> - </helper> - <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="copy" stepKey="copyProduct1BaseImage"> - <argument name="source">dev/tests/acceptance/tests/_data/{{ImportProductSimple2_Configurable.baseImage}}</argument> - <argument name="destination">var/import/images/{{ImportProduct_Configurable.name}}/{{ImportProductSimple2_Configurable.baseImage}}</argument> - </helper> - <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="copy" stepKey="copyProduct2BaseImage"> - <argument name="source">dev/tests/acceptance/tests/_data/{{ImportProductSimple1_Configurable.baseImage}}</argument> - <argument name="destination">var/import/images/{{ImportProduct_Configurable.name}}/{{ImportProductSimple1_Configurable.baseImage}}</argument> - </helper> - </before> - <after> - <helper class="Magento\Catalog\Test\Mftf\Helper\LocalFileAssertions" method="deleteDirectory" stepKey="deleteProductImageDirectory"> - <argument name="path">var/import/images/{{ImportProduct_Configurable.name}}</argument> - </helper> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct"> - <argument name="sku" value="import-product-configurable"/> - </actionGroup> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct2"> - <argument name="sku" value="import-product-simple1-configurable"/> - </actionGroup> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct3"> - <argument name="sku" value="import-product-simple2-configurable"/> - </actionGroup> - <actionGroup ref="DeleteProductBySkuActionGroup" stepKey="deleteConfigurableProduct4"> - <argument name="sku" value="import-product-simple3-configurable"/> - </actionGroup> - <actionGroup ref="AdminDeleteProductAttributeByLabelActionGroup" stepKey="deleteAttribute"> - <argument name="productAttributeLabel" value="Set Size" /> - </actionGroup> - <!-- Logout --> - <actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/> - </after> - <!--Create text swatch attribute with 3 options: 4, 24 and 30--> - <actionGroup ref="AddTextSwatchToProductActionGroup" stepKey="addSizeAttribute"> - <argument name="attributeName" value="{{SwatchProductSizeAttribute.frontend_label}}"/> - <argument name="attributeCode" value="{{SwatchProductSizeAttribute.attribute_code}}"/> - <argument name="option1" value="4"/> - <argument name="option2" value="24"/> - <argument name="option3" value="30"/> - </actionGroup> - - <!-- Go to created attribute (attribute page) --> - <actionGroup ref="NavigateToEditProductAttributeActionGroup" stepKey="navigateToSkuProductAttribute"> - <argument name="ProductAttribute" value="{{SwatchProductSizeAttribute.frontend_label}}"/> - </actionGroup> - <!-- Set 'yes' value for option "Update Product Preview Image" --> - <actionGroup ref="AdminUpdateProductPreviewImageActionGroup" stepKey="setUpdateProductPreviewImage" after="navigateToSkuProductAttribute"/> - <!-- Save Product Attribute --> - <actionGroup ref="SaveProductAttributeActionGroup" stepKey="saveAttribute" after="setUpdateProductPreviewImage"/> - - <actionGroup ref="AdminOpenAttributeSetGridPageActionGroup" stepKey="openAttributeSetPage"/> - - <!-- From grid, click on attribute set Default --> - <actionGroup ref="AdminOpenAttributeSetByNameActionGroup" stepKey="openDefaultAttributeSet"/> - - <!-- Add Product Attribute to Default attribute by dragging and dropping this to the 'Project Details' folder. Then Save. --> - <actionGroup ref="AssignAttributeToGroupActionGroup" stepKey="assignAttributeToGroup"> - <argument name="group" value="Product Details"/> - <argument name="attribute" value="{{SwatchProductSizeAttribute.attribute_code}}"/> - </actionGroup> - <actionGroup ref="SaveAttributeSetActionGroup" stepKey="saveAttributeSet"/> - - <actionGroup ref="AdminImportProductsWithCustomImagesDirectoryActionGroup" stepKey="adminImportProduct"> - <argument name="behavior" value="Add/Update"/> - <argument name="importFile" value="import_configurable_product_same_images.csv"/> - <argument name="imagesFileDirectory" value="{{ImportProduct_Configurable.name}}"/> - </actionGroup> - <waitForPageLoad time="30" stepKey="waitForSaveImportProduct"/> - - <!-- Open the configurable product page on storefront --> - <actionGroup ref="OpenStoreFrontProductPageActionGroup" stepKey="goToProductPage"> - <argument name="productUrlKey" value="{{ImportProduct_Configurable.name}}"/> - </actionGroup> - <!-- Select first option --> - <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectFirstOptionValue"> - <argument name="optionName" value="4"/> - </actionGroup> - <seeElement selector="{{StorefrontProductMediaSection.productImageInFotorama(ImportProductSimple3_Configurable.baseImage)}}" stepKey="seeFirstImageInRibbon"/> - <!-- Select second option --> - <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectSecondOptionValue"> - <argument name="optionName" value="24"/> - </actionGroup> - <!-- Select third option --> - <actionGroup ref="StorefrontSelectSwatchOptionOnProductPageActionGroup" stepKey="selectThirdOptionValue"> - <argument name="optionName" value="30"/> - </actionGroup> - </test> -</tests> diff --git a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js index 0fb819aee4c9d..6782a87b02a9f 100644 --- a/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js +++ b/app/code/Magento/Swatches/view/base/web/js/swatch-renderer.js @@ -1247,12 +1247,17 @@ define([ * @param {Array} images */ _setImageType: function (images) { + var initial = this.options.mediaGalleryInitial[0].img; - images.map(function (img) { - if (!img.type) { - img.type = 'image'; - } - }); + if (images[0].img === initial) { + images = $.extend(true, [], this.options.mediaGalleryInitial); + } else { + images.map(function (img) { + if (!img.type) { + img.type = 'image'; + } + }); + } return images; }, diff --git a/dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv b/dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv deleted file mode 100644 index d336d7279079f..0000000000000 --- a/dev/tests/acceptance/tests/_data/import_configurable_product_same_images.csv +++ /dev/null @@ -1,5 +0,0 @@ -sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,deferred_stock_update,use_config_deferred_stock_update,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,associated_skus,downloadable_links,downloadable_samples,configurable_variations,configurable_variation_labels -import-product-simple1-configurable,,Default,simple,,base,import-product-simple1-configurable,,,1,1,Taxable Goods,Search,11,,,,import-product-simple1-configurable,,,,magento-logo.png,Magento Logo,magento-logo.png,Magento Logo,magento-logo.png,Magento Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,set_size=24,101,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,"magento-logo.png,m-logo.gif,adobe-base.jpg",,,,,,,,,,,,,, -import-product-simple2-configurable,,Default,simple,,base,import-product-simple2-configurable,,,2,1,Taxable Goods,Search,12,,,,import-product-simple2-configurable,,,,m-logo.gif,M Logo,m-logo.gif,M Logo,m-logo.gif,M Logo,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,set_size=30,102,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,"m-logo.gif,adobe-base.jpg,magento-logo.png",,,,,,,,,,,,,, -import-product-simple3-configurable,,Default,simple,,base,import-product-simple3-configurable,,,3,1,Taxable Goods,Search,13,,,,import-product-simple3-configurable,,,,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,set_size=4,103,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,"adobe-base.jpg,m-logo.gif,magento-logo.png",,,,,,,,,,,,,, -import-product-configurable,,Default,configurable,Default Category,base,import-product-configurable,,,,1,Taxable Goods,"Catalog, Search",,,,,import-product-configurable,,,,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,adobe-base.jpg,Adobe Base,,,"10/5/20, 4:58 PM","10/5/20, 4:58 PM",,,Block after Info Column,,,,No,,,,,,,Use config,China,,,0,1,0,0,1,1,1,10000,1,1,1,1,1,1,1,1,1,0,0,0,0,1,,,,,,,adobe-base.jpg,,,,,,,,,,,,,"sku=import-product-simple1-configurable,set_size=24|sku=import-product-simple2-configurable,set_size=30|sku=import-product-simple3-configurable,set_size=4",set_size=Set Size \ No newline at end of file