From a8bcd7dbb774d693f7a7fdeadddcae6f9434d7c6 Mon Sep 17 00:00:00 2001 From: Nikita Tychuk Date: Fri, 22 Mar 2019 18:59:39 +0200 Subject: [PATCH 1/2] REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Add conditions for multiselect attribute validation. REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Create unit test for app/code/Magento/Eav/Model/TypeLocator/SimpleType.php. REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Code refactoring. REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Code refactoring. REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Change unit test functionality for app/code/Magento/Eav/Model/TypeLocator/SimpleType.php. REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Create api-functional test for the following case REST API multiselect attribute BC break between 2.1.8 and 2.3.0. Remove ObjectManager and setUp method. --- .../Eav/Model/TypeLocator/SimpleType.php | 5 + .../Unit/Model/TypeLocator/SimpleTypeTest.php | 155 ++++++++++++++++++ .../Api/ProductRepositoryInterfaceTest.php | 77 +++++++-- 3 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 app/code/Magento/Eav/Test/Unit/Model/TypeLocator/SimpleTypeTest.php diff --git a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php index 73b0516117df6..9628ff6124c04 100644 --- a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php +++ b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php @@ -50,6 +50,11 @@ public function getType($attributeCode, $entityType) } catch (NoSuchEntityException $exception) { return TypeProcessor::NORMALIZED_ANY_TYPE; } + + if ($attribute->getFrontendInput() === 'multiselect') { + return TypeProcessor::NORMALIZED_ANY_TYPE; + } + $backendType = $attribute->getBackendType(); $backendTypeMap = [ 'static' => TypeProcessor::NORMALIZED_ANY_TYPE, diff --git a/app/code/Magento/Eav/Test/Unit/Model/TypeLocator/SimpleTypeTest.php b/app/code/Magento/Eav/Test/Unit/Model/TypeLocator/SimpleTypeTest.php new file mode 100644 index 0000000000000..0dbec5f741874 --- /dev/null +++ b/app/code/Magento/Eav/Test/Unit/Model/TypeLocator/SimpleTypeTest.php @@ -0,0 +1,155 @@ +createMock(AttributeRepository::class); + $attributeRepositoryMock->expects($this->any()) + ->method('get') + ->willThrowException($getException); + + /** @var ServiceTypeListInterface|\PHPUnit_Framework_MockObject_MockObject $serviceTypeListMock */ + $serviceTypeListMock = $this->createMock(ServiceTypeListInterface::class); + + /** @var SimpleType|\PHPUnit_Framework_MockObject_MockObject $simpleType */ + $simpleType = new SimpleType( + $attributeRepositoryMock, + $serviceTypeListMock + ); + + $this->assertSame($expected, $simpleType->getType('testAttributeCode', 'testEntityType')); + } + + /** + * Test testGetType method + * @return void + */ + public function testGetTypeWithMultiselectFrontendInput() + { + $getFrontendInputReturn = 'multiselect'; + $expected = TypeProcessor::NORMALIZED_ANY_TYPE; + + /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $attributeMock */ + $attributeMock = $this->createMock(Attribute::class); + $attributeMock->expects($this->any()) + ->method('getFrontendInput') + ->willReturn($getFrontendInputReturn); + + /** @var AttributeRepository|\PHPUnit_Framework_MockObject_MockObject $attributeRepositoryMock */ + $attributeRepositoryMock = $this->createMock(AttributeRepository::class); + $attributeRepositoryMock->expects($this->any()) + ->method('get') + ->willReturn($attributeMock); + + /** @var ServiceTypeListInterface|\PHPUnit_Framework_MockObject_MockObject $serviceTypeListMock */ + $serviceTypeListMock = $this->createMock(ServiceTypeListInterface::class); + + /** @var SimpleType|\PHPUnit_Framework_MockObject_MockObject $simpleType */ + $simpleType = new SimpleType( + $attributeRepositoryMock, + $serviceTypeListMock + ); + + $this->assertSame($expected, $simpleType->getType('testAttributeCode', 'testEntityType')); + } + + /** + * Test testGetType method + * @return void + */ + public function testGetTypeWithBackendTypeInMap() + { + $getFrontendInputReturn = 'textarea'; + $getBackendTypeReturn = 'text'; + $expected = TypeProcessor::NORMALIZED_STRING_TYPE; + + /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $attributeMock */ + $attributeMock = $this->createMock(Attribute::class); + $attributeMock->expects($this->any()) + ->method('getFrontendInput') + ->willReturn($getFrontendInputReturn); + $attributeMock->expects($this->any()) + ->method('getBackendType') + ->willReturn($getBackendTypeReturn); + + /** @var AttributeRepository|\PHPUnit_Framework_MockObject_MockObject $attributeRepositoryMock */ + $attributeRepositoryMock = $this->createMock(AttributeRepository::class); + $attributeRepositoryMock->expects($this->any()) + ->method('get') + ->willReturn($attributeMock); + + /** @var ServiceTypeListInterface|\PHPUnit_Framework_MockObject_MockObject $serviceTypeListMock */ + $serviceTypeListMock = $this->createMock(ServiceTypeListInterface::class); + + /** @var SimpleType|\PHPUnit_Framework_MockObject_MockObject $simpleType */ + $simpleType = new SimpleType( + $attributeRepositoryMock, + $serviceTypeListMock + ); + + $this->assertSame($expected, $simpleType->getType('testAttributeCode', 'testEntityType')); + } + + /** + * Test testGetType method + * @return void + */ + public function testGetTypeWithBackendTypeNotInMap() + { + $getFrontendInputReturn = 'textarea'; + $getBackendTypeReturn = 'testBackendTypeNotInMap'; + $expected = TypeProcessor::NORMALIZED_ANY_TYPE; + + /** @var Attribute|\PHPUnit_Framework_MockObject_MockObject $attributeMock */ + $attributeMock = $this->createMock(Attribute::class); + $attributeMock->expects($this->any()) + ->method('getFrontendInput') + ->willReturn($getFrontendInputReturn); + $attributeMock->expects($this->any()) + ->method('getBackendType') + ->willReturn($getBackendTypeReturn); + + /** @var AttributeRepository|\PHPUnit_Framework_MockObject_MockObject $attributeRepositoryMock */ + $attributeRepositoryMock = $this->createMock(AttributeRepository::class); + $attributeRepositoryMock->expects($this->any()) + ->method('get') + ->willReturn($attributeMock); + + /** @var ServiceTypeListInterface|\PHPUnit_Framework_MockObject_MockObject $serviceTypeListMock */ + $serviceTypeListMock = $this->createMock(ServiceTypeListInterface::class); + + /** @var SimpleType|\PHPUnit_Framework_MockObject_MockObject $simpleType */ + $simpleType = new SimpleType( + $attributeRepositoryMock, + $serviceTypeListMock + ); + + $this->assertSame($expected, $simpleType->getType('testAttributeCode', 'testEntityType')); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index 1017fb6716709..ea501cff39732 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -1561,40 +1561,95 @@ public function testUpdateStatus() * Test saving product with custom attribute of multiselect type * * 1. Create multi-select attribute - * 2. Create product and set 2 options out of 3 to multi-select attribute - * 3. Verify that 2 options are selected - * 4. Unselect all options - * 5. Verify that non options are selected + * 2. Create product + * 3. Set 2 options out of 3 to multi-select attribute in string format + * 4. Verify that 2 options are selected * * @magentoApiDataFixture Magento/Catalog/_files/multiselect_attribute.php */ - public function testUpdateMultiselectAttributes() + public function testUpdateMultiselectAttributesWithStringValue() { $multiselectAttributeCode = 'multiselect_attribute'; $multiselectOptions = $this->getAttributeOptions($multiselectAttributeCode); - $option1 = $multiselectOptions[1]['value']; - $option2 = $multiselectOptions[2]['value']; + $option1Value = $multiselectOptions[1]['value']; + $option2Value = $multiselectOptions[2]['value']; $productData = $this->getSimpleProductData(); + + $multiselectValue = "{$option1Value},{$option2Value}"; + $productData['custom_attributes'] = [ + ['attribute_code' => $multiselectAttributeCode, 'value' => $multiselectValue] + ]; + $this->saveProduct($productData, 'all'); + + $expectedMultiselectValue = "{$option1Value},{$option2Value}"; + $this->assertMultiselectValue( + $productData[ProductInterface::SKU], + $multiselectAttributeCode, + $expectedMultiselectValue + ); + } + + /** + * Test saving product with custom attribute of multiselect type + * + * 1. Create multi-select attribute + * 2. Create product + * 3. Set 2 options out of 3 to multi-select attribute in array format + * 4. Verify that 2 options are selected + * + * @magentoApiDataFixture Magento/Catalog/_files/multiselect_attribute.php + */ + public function testUpdateMultiselectAttributesWithArrayValue() + { + $multiselectAttributeCode = 'multiselect_attribute'; + $multiselectOptions = $this->getAttributeOptions($multiselectAttributeCode); + $option1Value = $multiselectOptions[1]['value']; + $option2Value = $multiselectOptions[2]['value']; + + $productData = $this->getSimpleProductData(); + + $multiselectValue = ["{$option1Value}", "{$option2Value}"]; $productData['custom_attributes'] = [ - ['attribute_code' => $multiselectAttributeCode, 'value' => "{$option1},{$option2}"] + ['attribute_code' => $multiselectAttributeCode, 'value' => $multiselectValue] ]; $this->saveProduct($productData, 'all'); + $expectedMultiselectValue = "{$option1Value},{$option2Value}"; $this->assertMultiselectValue( $productData[ProductInterface::SKU], $multiselectAttributeCode, - "{$option1},{$option2}" + $expectedMultiselectValue ); + } + /** + * Test saving product with custom attribute of multiselect type + * + * 1. Create multi-select attribute + * 2. Create product + * 3. Unselect all options + * 4. Verify that non options are selected + * + * @magentoApiDataFixture Magento/Catalog/_files/multiselect_attribute.php + */ + public function testUpdateMultiselectAttributesWithEmptyValue() + { + $multiselectAttributeCode = 'multiselect_attribute'; + + $productData = $this->getSimpleProductData(); + + $multiselectValue = ""; $productData['custom_attributes'] = [ - ['attribute_code' => $multiselectAttributeCode, 'value' => ""] + ['attribute_code' => $multiselectAttributeCode, 'value' => $multiselectValue] ]; $this->saveProduct($productData, 'all'); + + $expectedMultiselectValue = ""; $this->assertMultiselectValue( $productData[ProductInterface::SKU], $multiselectAttributeCode, - "" + $expectedMultiselectValue ); } From 5162d508e5c5d540edebe8100ae835a23c78caf7 Mon Sep 17 00:00:00 2001 From: Nazarn96 Date: Mon, 13 May 2019 11:44:43 +0300 Subject: [PATCH 2/2] magento/magento2#21901 static-test-fix --- .../Magento/Eav/Model/TypeLocator/SimpleType.php | 5 +++-- .../Catalog/Api/ProductRepositoryInterfaceTest.php | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php index 9628ff6124c04..efc92c432328b 100644 --- a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php +++ b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php @@ -31,6 +31,7 @@ class SimpleType implements CustomAttributeTypeLocatorInterface * Initialize dependencies. * * @param AttributeRepositoryInterface $attributeRepository + * @param ServiceTypeListInterface $serviceTypeList */ public function __construct( AttributeRepositoryInterface $attributeRepository, @@ -41,7 +42,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getType($attributeCode, $entityType) { @@ -69,7 +70,7 @@ public function getType($attributeCode, $entityType) } /** - * {@inheritDoc} + * @inheritDoc */ public function getAllServiceDataInterfaces() { diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index ea501cff39732..98668ae7d3fff 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -663,6 +663,7 @@ public function testProductOptions() public function testProductWithMediaGallery() { $testImagePath = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'test_image.jpg'; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $encodedImage = base64_encode(file_get_contents($testImagePath)); //create a product with media gallery $filename1 = 'tiny1' . time() . '.jpg'; @@ -787,7 +788,9 @@ public function testUpdateWithExtensionAttributes(): void protected function updateProduct($product) { if (isset($product['custom_attributes'])) { - for ($i=0; $igetSimpleProductData(); - $multiselectValue = ["{$option1Value}", "{$option2Value}"]; $productData['custom_attributes'] = [ - ['attribute_code' => $multiselectAttributeCode, 'value' => $multiselectValue] + ['attribute_code' => $multiselectAttributeCode, 'value' => [$option1Value, $option2Value]] ]; $this->saveProduct($productData, 'all');