diff --git a/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php b/app/code/Magento/Eav/Model/TypeLocator/SimpleType.php index 73b0516117df6..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) { @@ -50,6 +51,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, @@ -64,7 +70,7 @@ public function getType($attributeCode, $entityType) } /** - * {@inheritDoc} + * @inheritDoc */ public function getAllServiceDataInterfaces() { 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..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; $igetAttributeOptions($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(); + $productData['custom_attributes'] = [ - ['attribute_code' => $multiselectAttributeCode, 'value' => "{$option1},{$option2}"] + ['attribute_code' => $multiselectAttributeCode, 'value' => [$option1Value, $option2Value]] ]; $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 ); }