From b65f72246608ece8222c0c8e09b87aaf4fda647b Mon Sep 17 00:00:00 2001 From: cspruiell Date: Thu, 20 Oct 2016 12:02:25 -0500 Subject: [PATCH 1/2] MAGETWO-58348: Cannot create configurable product with child by REST API - backport solution from 2.1 --- app/code/Magento/Catalog/Model/Product.php | 12 +- .../Model/LinkManagement.php | 101 +++++++++- .../Test/Unit/Model/LinkManagementTest.php | 89 +++++++-- .../ConfigurableProduct/i18n/en_US.csv | 2 + .../Api/LinkManagementTest.php | 172 +++++++++++++++++- .../_files/product_simple_77.php | 3 +- 6 files changed, 355 insertions(+), 24 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 9e9f18e011371..9fbd6b7184e87 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -22,7 +22,6 @@ * @method Product setHasError(bool $value) * @method \Magento\Catalog\Model\ResourceModel\Product getResource() * @method null|bool getHasError() - * @method Product setAssociatedProductIds(array $productIds) * @method array getAssociatedProductIds() * @method Product setNewVariationsAttributeSetId(int $value) * @method int getNewVariationsAttributeSetId() @@ -2614,4 +2613,15 @@ private function getMediaGalleryProcessor() } return $this->mediaGalleryProcessor; } + + /** + * Set the associated products + * @param array $productIds + * @return $this + */ + public function setAssociatedProductIds(array $productIds) + { + $this->getExtensionAttributes()->setConfigurableProductLinks($productIds); + return $this; + } } diff --git a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php index 0fdfbd3bfa172..5575d6f7ef56f 100644 --- a/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php +++ b/app/code/Magento/ConfigurableProduct/Model/LinkManagement.php @@ -32,6 +32,16 @@ class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementI */ private $dataObjectHelper; + /** + * @var \Magento\ConfigurableProduct\Helper\Product\Options\Factory; + */ + private $optionsFactory; + + /** + * @var \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory + */ + private $attributeFactory; + /** * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param \Magento\Catalog\Api\Data\ProductInterfaceFactory $productFactory @@ -102,9 +112,28 @@ public function addChild($sku, $childSku) throw new StateException(__('Product has been already attached')); } + $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions(); + if (empty($configurableProductOptions)) { + throw new StateException(__('Parent product does not have configurable product options')); + } + + $attributeIds = []; + foreach ($configurableProductOptions as $configurableProductOption) { + $attributeCode = $configurableProductOption->getProductAttribute()->getAttributeCode(); + if (!$child->getData($attributeCode)) { + throw new StateException(__('Child product does not have attribute value %1', $attributeCode)); + } + $attributeIds[] = $configurableProductOption->getAttributeId(); + } + $configurableOptionData = $this->getConfigurableAttributesData($attributeIds); + + /** @var \Magento\ConfigurableProduct\Helper\Product\Options\Factory $optionFactory */ + $optionFactory = $this->getOptionsFactory(); + $options = $optionFactory->create($configurableOptionData); $childrenIds[] = $child->getId(); + $product->getExtensionAttributes()->setConfigurableProductOptions($options); $product->getExtensionAttributes()->setConfigurableProductLinks($childrenIds); - $product->save(); + $this->productRepository->save($product); return true; } @@ -133,7 +162,75 @@ public function removeChild($sku, $childSku) throw new NoSuchEntityException(__('Requested option doesn\'t exist')); } $product->getExtensionAttributes()->setConfigurableProductLinks($ids); - $product->save(); + $this->productRepository->save($product); return true; } + + /** + * Get Options Factory + * + * @return \Magento\ConfigurableProduct\Helper\Product\Options\Factory + * + * @deprecated + */ + private function getOptionsFactory() + { + if (!$this->optionsFactory) { + $this->optionsFactory = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class); + } + return $this->optionsFactory; + } + + /** + * Get Attribute Factory + * + * @return \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory + * + * @deprecated + */ + private function getAttributeFactory() + { + if (!$this->attributeFactory) { + $this->attributeFactory = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory::class); + } + return $this->attributeFactory; + } + + /** + * Get Configurable Attribute Data + * + * @param int[] $attributeIds + * @return array + */ + private function getConfigurableAttributesData($attributeIds) + { + $configurableAttributesData = []; + $attributeValues = []; + $attributes = $this->getAttributeFactory()->create() + ->getCollection() + ->addFieldToFilter('attribute_id', $attributeIds) + ->getItems(); + foreach ($attributes as $attribute) { + foreach ($attribute->getOptions() as $option) { + if ($option->getValue()) { + $attributeValues[] = [ + 'label' => $option->getLabel(), + 'attribute_id' => $attribute->getId(), + 'value_index' => $option->getValue(), + ]; + } + } + $configurableAttributesData[] = + [ + 'attribute_id' => $attribute->getId(), + 'code' => $attribute->getAttributeCode(), + 'label' => $attribute->getStoreLabel(), + 'values' => $attributeValues, + ]; + } + + return $configurableAttributesData; + } } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php index 6b69888e6dd09..5a7886ea3ea64 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/LinkManagementTest.php @@ -6,8 +6,8 @@ namespace Magento\ConfigurableProduct\Test\Unit\Model; +use Magento\ConfigurableProduct\Model\LinkManagement; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; -use Magento\ConfigurableProduct\Test\Unit\Model\Product\ProductExtensionAttributes; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -146,15 +146,59 @@ public function testAddChild() $configurable = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) ->disableOriginalConstructor() + ->setMethods(['getId', 'getExtensionAttributes']) + ->getMock(); + $simple = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->setMethods(['getId', 'getData']) ->getMock(); - $configurable->expects($this->any())->method('getId')->will($this->returnValue(666)); + $extensionAttributesMock = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtension::class) + ->disableOriginalConstructor() + ->setMethods([ + 'getConfigurableProductOptions', 'setConfigurableProductOptions', 'setConfigurableProductLinks' + ]) + ->getMock(); + $optionMock = $this->getMockBuilder(\Magento\ConfigurableProduct\Api\Data\Option::class) + ->disableOriginalConstructor() + ->setMethods(['getProductAttribute', 'getAttributeId']) + ->getMock(); + $productAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class) + ->disableOriginalConstructor() + ->setMethods(['getAttributeCode']) + ->getMock(); + $optionsFactoryMock = $this->getMockBuilder(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $reflectionClass = new \ReflectionClass(\Magento\ConfigurableProduct\Model\LinkManagement::class); + $optionsFactoryReflectionProperty = $reflectionClass->getProperty('optionsFactory'); + $optionsFactoryReflectionProperty->setAccessible(true); + $optionsFactoryReflectionProperty->setValue($this->object, $optionsFactoryMock); - $simple = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + $attributeFactoryMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory::class) ->disableOriginalConstructor() + ->setMethods(['create']) ->getMock(); + $attributeFactoryReflectionProperty = $reflectionClass->getProperty('attributeFactory'); + $attributeFactoryReflectionProperty->setAccessible(true); + $attributeFactoryReflectionProperty->setValue($this->object, $attributeFactoryMock); - $simple->expects($this->any())->method('getId')->will($this->returnValue(999)); + $attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class) + ->disableOriginalConstructor() + ->setMethods(['getCollection', 'getOptions', 'getId', 'getAttributeCode', 'getStoreLabel']) + ->getMock(); + $attributeOptionMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\Option::class) + ->disableOriginalConstructor() + ->setMethods(['getValue', 'getLabel']) + ->getMock(); + + $attributeCollectionMock = $this->getMockBuilder( + \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection::class + ) + ->disableOriginalConstructor() + ->setMethods(['addFieldToFilter', 'getItems']) + ->getMock(); $this->productRepository->expects($this->at(0))->method('get')->with($productSku)->willReturn($configurable); $this->productRepository->expects($this->at(1))->method('get')->with($childSku)->willReturn($simple); @@ -164,15 +208,30 @@ public function testAddChild() $this->returnValue([0 => [1, 2, 3]]) ); - $extensionAttributes = $this->getMockBuilder(ProductExtensionAttributes::class) - ->setMethods(['setConfigurableProductLinks']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); + $configurable->expects($this->any())->method('getId')->will($this->returnValue(666)); + $simple->expects($this->any())->method('getId')->will($this->returnValue(999)); + + $configurable->expects($this->any())->method('getExtensionAttributes')->willReturn($extensionAttributesMock); + $extensionAttributesMock->expects($this->any()) + ->method('getConfigurableProductOptions') + ->willReturn([$optionMock]); + $optionMock->expects($this->any())->method('getProductAttribute')->willReturn($productAttributeMock); + $productAttributeMock->expects($this->any())->method('getAttributeCode')->willReturn('color'); + $simple->expects($this->any())->method('getData')->willReturn('color'); + $optionMock->expects($this->any())->method('getAttributeId')->willReturn('1'); - $configurable->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributes); - $extensionAttributes->expects($this->once())->method('setConfigurableProductLinks')->willReturnSelf(); + $optionsFactoryMock->expects($this->any())->method('create')->willReturn([$optionMock]); + $attributeFactoryMock->expects($this->any())->method('create')->willReturn($attributeMock); + $attributeMock->expects($this->any())->method('getCollection')->willReturn($attributeCollectionMock); + $attributeCollectionMock->expects($this->any())->method('addFieldToFilter')->willReturnSelf(); + $attributeCollectionMock->expects($this->any())->method('getItems')->willReturn([$attributeMock]); - $configurable->expects($this->once())->method('save'); + $attributeMock->expects($this->any())->method('getOptions')->willReturn([$attributeOptionMock]); + + $extensionAttributesMock->expects($this->any())->method('setConfigurableProductOptions'); + $extensionAttributesMock->expects($this->any())->method('setConfigurableProductLinks'); + + $this->productRepository->expects($this->once())->method('save'); $this->assertTrue(true, $this->object->addChild($productSku, $childSku)); } @@ -243,15 +302,13 @@ public function testRemoveChild() $productType->expects($this->once())->method('getUsedProducts') ->will($this->returnValue([$option])); - $extensionAttributes = $this->getMockBuilder(ProductExtensionAttributes::class) + $extensionAttributesMock = $this->getMockBuilder(\Magento\Framework\Api\ExtensionAttributesInterface::class) ->setMethods(['setConfigurableProductLinks']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $product->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributes); - $extensionAttributes->expects($this->once())->method('setConfigurableProductLinks')->willReturnSelf(); - - $product->expects($this->once())->method('save'); + $product->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttributesMock); + $this->productRepository->expects($this->once())->method('save'); $this->assertTrue($this->object->removeChild($productSku, $childSku)); } diff --git a/app/code/Magento/ConfigurableProduct/i18n/en_US.csv b/app/code/Magento/ConfigurableProduct/i18n/en_US.csv index 59ae9a2016707..bb3848dc45d84 100644 --- a/app/code/Magento/ConfigurableProduct/i18n/en_US.csv +++ b/app/code/Magento/ConfigurableProduct/i18n/en_US.csv @@ -117,6 +117,8 @@ Done,Done "Please select attribute(s).","Please select attribute(s)." "Generate Products","Generate Products" "Configurable Product Image","Configurable Product Image" +"Parent product does not have configurable product options","Parent product does not have configurable product options" +"Child product does not have attribute value %1","Child product does not have attribute value %1" Select...,Select... Status,Status ID,ID diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php index e4129a0739912..2bc98060524e3 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php @@ -6,12 +6,33 @@ */ namespace Magento\ConfigurableProduct\Api; +use Magento\Eav\Model\AttributeRepository; + class LinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract { const SERVICE_NAME = 'configurableProductLinkManagementV1'; const SERVICE_VERSION = 'V1'; const RESOURCE_PATH = '/V1/configurable-products'; + /** + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $objectManager; + + /** + * @var AttributeRepository + */ + protected $attributeRepository; + + /** + * Execute per test initialization + */ + public function setUp() + { + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->attributeRepository = $this->objectManager->get(\Magento\Eav\Model\AttributeRepository::class); + } + /** * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php */ @@ -40,14 +61,75 @@ public function testGetChildren() } /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_simple_77.php * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_simple_77.php * @magentoApiDataFixture Magento/ConfigurableProduct/_files/delete_association.php */ public function testAddChild() { $productSku = 'configurable'; $childSku = 'simple_77'; + $res = $this->addChild($productSku, $childSku); + $this->assertTrue($res); + } + + /** + * Test case to cover bug MAGETWO-58401 + * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php + */ + public function testAddChildFullRestCreation() + { + $productSku = 'configurable-product-sku'; + $childSku = 'simple-product-sku'; + + $this->createConfigurableProduct($productSku); + $attribute = $this->attributeRepository->get('catalog_product', 'test_configurable'); + $attributeValue = $attribute->getOptions()[1]->getValue(); + $this->addOptionToConfigurableProduct($productSku, $attribute->getAttributeId(), $attributeValue); + $this->createSimpleProduct($childSku, $attributeValue); + $res = $this->addChild($productSku, $childSku); + $this->assertTrue($res); + + // confirm that the simple product was added + $children = $this->getChildren($productSku); + $added = false; + foreach ($children as $child) { + if ($child['sku'] == $childSku) { + $added = true; + break; + } + } + $this->assertTrue($added); + + // clean up products + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/products/' . $productSku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE + ], + 'soap' => [ + 'service' => 'catalogProductRepositoryV1', + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => 'catalogProductRepositoryV1DeleteById', + ], + ]; + $this->_webApiCall($serviceInfo, ['sku' => $productSku]); + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/products/' . $childSku, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE + ], + 'soap' => [ + 'service' => 'catalogProductRepositoryV1', + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => 'catalogProductRepositoryV1DeleteById', + ], + ]; + $this->_webApiCall($serviceInfo, ['sku' => $childSku]); + } + + private function addChild($productSku, $childSku) + { $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '/' . $productSku . '/child', @@ -59,8 +141,90 @@ public function testAddChild() 'operation' => self::SERVICE_NAME . 'AddChild' ] ]; - $res = $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'childSku' => $childSku]); - $this->assertTrue($res); + return $this->_webApiCall($serviceInfo, ['sku' => $productSku, 'childSku' => $childSku]); + } + + protected function createConfigurableProduct($productSku) + { + $requestData = [ + 'product' => [ + 'sku' => $productSku, + 'name' => 'configurable-product-' . $productSku, + 'type_id' => 'configurable', + 'price' => 50, + 'attribute_set_id' => 4 + ] + ]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/products', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST + ], + 'soap' => [ + 'service' => 'catalogProductRepositoryV1', + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => 'catalogProductRepositoryV1Save', + ], + ]; + return $this->_webApiCall($serviceInfo, $requestData); + } + + protected function addOptionToConfigurableProduct($productSku, $attributeId, $attributeValue) + { + $requestData = [ + 'sku' => $productSku, + 'option' => [ + 'attribute_id' => $attributeId, + 'label' => 'test_configurable', + 'position' => 0, + 'is_use_default' => true, + 'values' => [ + ['value_index' => $attributeValue], + ] + ] + ]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/configurable-products/'. $productSku .'/options', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => 'configurableProductOptionRepositoryV1', + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => 'configurableProductOptionRepositoryV1Save', + ], + ]; + return $this->_webApiCall($serviceInfo, $requestData); + } + + protected function createSimpleProduct($sku, $attributeValue) + { + $requestData = [ + 'product' => [ + 'sku' => $sku, + 'name' => 'simple-product-' . $sku, + 'type_id' => 'simple', + 'attribute_set_id' => 4, + 'price' => 3.62, + 'status' => 1, + 'visibility' => 4, + 'custom_attributes' => [ + ['attribute_code' => 'test_configurable', 'value' => $attributeValue], + ] + ] + ]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/products', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => 'catalogProductRepositoryV1', + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => 'catalogProductRepositoryV1Save', + ], + ]; + return $this->_webApiCall($serviceInfo, $requestData); } /** @@ -93,7 +257,7 @@ protected function removeChild($productSku, $childSku) /** * @param string $productSku - * @return string + * @return string[] */ protected function getChildren($productSku) { diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php index ff08056e4b18d..90662c6d259ed 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php @@ -72,7 +72,8 @@ 'is_in_stock' => 1, ] )->setCanSaveCustomOptions(true) - ->setHasOptions(true); + ->setHasOptions(true) + ->setCustomAttribute('test_configurable', 42); $oldOptions = [ [ From ee995f28b483ef90f02b08a091f3cebc217391ab Mon Sep 17 00:00:00 2001 From: cspruiell Date: Fri, 21 Oct 2016 14:27:57 -0500 Subject: [PATCH 2/2] MAGETWO-58348: Cannot create configurable product with child by REST API - code cleanup --- app/code/Magento/Catalog/Model/Product.php | 1 + app/code/Magento/ConfigurableProduct/i18n/en_US.csv | 2 -- .../Magento/ConfigurableProduct/Api/LinkManagementTest.php | 3 ++- .../Magento/ConfigurableProduct/_files/product_simple_77.php | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 9fbd6b7184e87..c913c82de1acd 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -2616,6 +2616,7 @@ private function getMediaGalleryProcessor() /** * Set the associated products + * * @param array $productIds * @return $this */ diff --git a/app/code/Magento/ConfigurableProduct/i18n/en_US.csv b/app/code/Magento/ConfigurableProduct/i18n/en_US.csv index bb3848dc45d84..59ae9a2016707 100644 --- a/app/code/Magento/ConfigurableProduct/i18n/en_US.csv +++ b/app/code/Magento/ConfigurableProduct/i18n/en_US.csv @@ -117,8 +117,6 @@ Done,Done "Please select attribute(s).","Please select attribute(s)." "Generate Products","Generate Products" "Configurable Product Image","Configurable Product Image" -"Parent product does not have configurable product options","Parent product does not have configurable product options" -"Child product does not have attribute value %1","Child product does not have attribute value %1" Select...,Select... Status,Status ID,ID diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php index 2bc98060524e3..1a06be978d34c 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php @@ -74,7 +74,8 @@ public function testAddChild() } /** - * Test case to cover bug MAGETWO-58401 + * Test the full flow of creating a configurable product and adding a child via REST + * * @magentoApiDataFixture Magento/ConfigurableProduct/_files/configurable_attribute.php */ public function testAddChildFullRestCreation() diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php index 90662c6d259ed..0d8361b4751e3 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_simple_77.php @@ -1,5 +1,7 @@