From d143eb2ad72de6586806eb5bf27526e946e00a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Sun, 5 Apr 2020 13:18:15 +0200 Subject: [PATCH 1/5] Fix #21025 - Missing "Apply To" when editing Product attributes --- .../Product/Attribute/Edit/Tab/Advanced.php | 68 +++++++----- .../Adminhtml/Product/Attribute/Save.php | 8 +- .../Model/Attribute/Source/ApplyTo.php | 45 ++++++++ .../Attribute/Edit/Tab/AdvancedTest.php | 105 ++++++++++-------- .../Adminhtml/Product/Attribute/SaveTest.php | 99 ++++++++--------- 5 files changed, 200 insertions(+), 125 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Attribute/Source/ApplyTo.php diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php index 89239a2e3e608..3b6cd710cab28 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php @@ -6,13 +6,18 @@ namespace Magento\Catalog\Block\Adminhtml\Product\Attribute\Edit\Tab; +use Magento\Backend\Block\Template\Context; use Magento\Backend\Block\Widget\Form\Generic; +use Magento\Catalog\Model\Attribute\Source\ApplyTo; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Config\Model\Config\Source\Yesno; use Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker; use Magento\Eav\Helper\Data; +use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Data\FormFactory; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Registry; use Magento\Framework\Stdlib\DateTime; /** @@ -29,7 +34,7 @@ class Advanced extends Generic * * @var Data */ - protected $_eavData = null; + protected $_eavData; /** * @var Yesno @@ -47,27 +52,38 @@ class Advanced extends Generic private $propertyLocker; /** - * @param \Magento\Backend\Block\Template\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Magento\Framework\Data\FormFactory $formFactory + * @var ApplyTo + */ + private $applyTo; + + /** + * @param Context $context + * @param Registry $registry + * @param FormFactory $formFactory * @param Yesno $yesNo * @param Data $eavData * @param array $disableScopeChangeList * @param array $data + * @param PropertyLocker|null $propertyLocker + * @param ApplyTo|null $applyTo */ public function __construct( - \Magento\Backend\Block\Template\Context $context, - \Magento\Framework\Registry $registry, - \Magento\Framework\Data\FormFactory $formFactory, + Context $context, + Registry $registry, + FormFactory $formFactory, Yesno $yesNo, Data $eavData, array $disableScopeChangeList = ['sku'], - array $data = [] + array $data = [], + ?PropertyLocker $propertyLocker = null, + ?ApplyTo $applyTo = null ) { $this->_yesNo = $yesNo; $this->_eavData = $eavData; $this->disableScopeChangeList = $disableScopeChangeList; parent::__construct($context, $registry, $formFactory, $data); + $this->propertyLocker = $propertyLocker ?? ObjectManager::getInstance()->get(PropertyLocker::class); + $this->applyTo = $applyTo ?? ObjectManager::getInstance()->get(ApplyTo::class); } /** @@ -230,22 +246,35 @@ protected function _prepareForm() ] ); + $fieldset->addField( + 'apply_to', + 'multiselect', + [ + 'name' => 'apply_to', + 'label' => __('Apply To'), + 'title' => __('Apply To'), + 'values' => $this->applyTo->toOptionArray(), + 'value' => $attributeObject->getApplyTo() + ] + ); + if ($attributeObject->getId()) { $form->getElement('attribute_code')->setDisabled(1); if (!$attributeObject->getIsUserDefined()) { $form->getElement('is_unique')->setDisabled(1); + $form->getElement('apply_to')->setDisabled(1); } } $scopes = [ - \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE => __('Store View'), - \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_WEBSITE => __('Website'), - \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL => __('Global'), + ScopedAttributeInterface::SCOPE_STORE => __('Store View'), + ScopedAttributeInterface::SCOPE_WEBSITE => __('Website'), + ScopedAttributeInterface::SCOPE_GLOBAL => __('Global'), ]; if ($attributeObject->getAttributeCode() == 'status' || $attributeObject->getAttributeCode() == 'tax_class_id' ) { - unset($scopes[\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE]); + unset($scopes[ScopedAttributeInterface::SCOPE_STORE]); } $fieldset->addField( @@ -266,7 +295,7 @@ protected function _prepareForm() $form->getElement('is_global')->setDisabled(1); } $this->setForm($form); - $this->getPropertyLocker()->lock($form); + $this->propertyLocker->lock($form); return $this; } @@ -291,19 +320,6 @@ private function getAttributeObject() return $this->_coreRegistry->registry('entity_attribute'); } - /** - * Get property locker - * - * @return PropertyLocker - */ - private function getPropertyLocker() - { - if (null === $this->propertyLocker) { - $this->propertyLocker = ObjectManager::getInstance()->get(PropertyLocker::class); - } - return $this->propertyLocker; - } - /** * Get localized date default value * diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 853cc65270306..13e4ce3540905 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -1,26 +1,25 @@ getIsUserDefined() && $model->getId()) { // Unset attribute field for system attributes unset($data['apply_to']); + } elseif (!isset($data['apply_to'])) { + $data['apply_to'] = []; } $model->addData($data); diff --git a/app/code/Magento/Catalog/Model/Attribute/Source/ApplyTo.php b/app/code/Magento/Catalog/Model/Attribute/Source/ApplyTo.php new file mode 100644 index 0000000000000..4b4dd6bc7b610 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Attribute/Source/ApplyTo.php @@ -0,0 +1,45 @@ +productTypeList = $productTypeList; + } + + /** + * @inheritDoc + */ + public function toOptionArray() + { + $result = []; + + foreach ($this->productTypeList->getProductTypes() as $productType) { + $result[] = [ + 'value' => $productType->getName(), + 'label' => $productType->getLabel() + ]; + } + + return $result; + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php index 4d9345d0b3f22..2507bb2fcb945 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php @@ -3,8 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Test\Unit\Block\Adminhtml\Product\Attribute\Edit\Tab; +use Magento\Backend\Block\Widget\Form\Element\ElementCreator; use Magento\Catalog\Block\Adminhtml\Product\Attribute\Edit\Tab\Advanced; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Config\Model\Config\Source\Yesno; @@ -17,58 +20,60 @@ use Magento\Framework\Data\FormFactory; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Registry; use Magento\Framework\Stdlib\DateTime; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** * Test product attribute add/edit advanced form tab * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class AdvancedTest extends \PHPUnit\Framework\TestCase +class AdvancedTest extends TestCase { /** * @var Advanced */ - protected $block; + private $block; /** * @var FormFactory|MockObject */ - protected $formFactory; + private $formFactoryMock; /** * @var Registry|MockObject */ - protected $registry; + private $registryMock; /** * @var TimezoneInterface|MockObject */ - protected $localeDate; + private $localeDateMock; /** * @var Yesno|MockObject */ - protected $yesNo; + private $yesNoMock; /** * @var EavHelper|MockObject */ - protected $eavData; + private $eavDataMock; /** * @var Filesystem|MockObject */ - protected $filesystem; + private $filesystemMock; /** * @var PropertyLocker|MockObject */ - protected $propertyLocker; + private $propertyLockerMock; /** * @inheritdoc @@ -76,24 +81,32 @@ class AdvancedTest extends \PHPUnit\Framework\TestCase protected function setUp() { $objectManager = new ObjectManager($this); - $this->registry = $this->createMock(Registry::class); - $this->formFactory = $this->createMock(FormFactory::class); - $this->yesNo = $this->createMock(Yesno::class); - $this->localeDate = $this->createMock(TimezoneInterface::class); - $this->eavData = $this->createMock(EavHelper::class); - $this->filesystem = $this->createMock(Filesystem::class); - $this->propertyLocker = $this->createMock(PropertyLocker::class); + $this->registryMock = $this->createMock(Registry::class); + $this->formFactoryMock = $this->createMock(FormFactory::class); + $this->yesNoMock = $this->createMock(Yesno::class); + $this->localeDateMock = $this->createMock(TimezoneInterface::class); + $this->eavDataMock = $this->createMock(EavHelper::class); + $this->filesystemMock = $this->createMock(Filesystem::class); + $this->propertyLockerMock = $this->createMock(PropertyLocker::class); + + $objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $objectManagerMock->method('get') + ->with(ElementCreator::class) + ->willReturn( + $objectManager->getObject(ElementCreator::class) + ); + \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); $this->block = $objectManager->getObject( Advanced::class, [ - 'registry' => $this->registry, - 'formFactory' => $this->formFactory, - 'localeDate' => $this->localeDate, - 'yesNo' => $this->yesNo, - 'eavData' => $this->eavData, - 'filesystem' => $this->filesystem, - 'propertyLocker' => $this->propertyLocker, + 'registry' => $this->registryMock, + 'formFactory' => $this->formFactoryMock, + 'localeDate' => $this->localeDateMock, + 'yesNo' => $this->yesNoMock, + 'eavData' => $this->eavDataMock, + 'filesystem' => $this->filesystemMock, + 'propertyLocker' => $this->propertyLockerMock ] ); } @@ -128,19 +141,19 @@ public function testToHtml() $formElement = $this->createPartialMock(Text::class, ['setDisabled']); $directoryReadInterface = $this->createMock(ReadInterface::class); - $this->registry->expects($this->any())->method('registry')->with('entity_attribute') + $this->registryMock->method('registry')->with('entity_attribute') ->willReturn($attributeModel); - $this->formFactory->expects($this->any())->method('create')->willReturn($form); - $form->expects($this->any())->method('addFieldset')->willReturn($fieldSet); - $form->expects($this->any())->method('getElement')->willReturn($formElement); - $fieldSet->expects($this->any())->method('addField')->willReturnSelf(); - $attributeModel->expects($this->any())->method('getDefaultValue')->willReturn($defaultValue); - $attributeModel->expects($this->any())->method('setDisabled')->willReturnSelf(); - $attributeModel->expects($this->any())->method('getId')->willReturn(1); - $attributeModel->expects($this->any())->method('getEntityType')->willReturn($entityType); - $attributeModel->expects($this->any())->method('getIsUserDefined')->willReturn(false); - $attributeModel->expects($this->any())->method('getAttributeCode')->willReturn('attribute_code'); - $attributeModel->expects($this->any())->method('getFrontendInput')->willReturn($frontendInput); + $this->formFactoryMock->method('create')->willReturn($form); + $form->method('addFieldset')->willReturn($fieldSet); + $form->method('getElement')->willReturn($formElement); + $fieldSet->method('addField')->willReturnSelf(); + $attributeModel->method('getDefaultValue')->willReturn($defaultValue); + $attributeModel->method('setDisabled')->willReturnSelf(); + $attributeModel->method('getId')->willReturn(1); + $attributeModel->method('getEntityType')->willReturn($entityType); + $attributeModel->method('getIsUserDefined')->willReturn(false); + $attributeModel->method('getAttributeCode')->willReturn('attribute_code'); + $attributeModel->method('getFrontendInput')->willReturn($frontendInput); $dateTimeMock = $this->createMock(\DateTime::class); $dateTimeMock->expects($this->once())->method('setTimezone')->with(new \DateTimeZone($timeZone)); @@ -148,21 +161,21 @@ public function testToHtml() ->method('format') ->with(DateTime::DATETIME_PHP_FORMAT) ->willReturn($localizedDefaultValue); - $this->localeDate->expects($this->any())->method('getDateFormat')->willReturn($dateFormat); - $this->localeDate->expects($this->any())->method('getTimeFormat')->willReturn($timeFormat); - $this->localeDate->expects($this->once())->method('getConfigTimezone')->willReturn($timeZone); - $this->localeDate->expects($this->once()) + $this->localeDateMock->method('getDateFormat')->willReturn($dateFormat); + $this->localeDateMock->method('getTimeFormat')->willReturn($timeFormat); + $this->localeDateMock->expects($this->once())->method('getConfigTimezone')->willReturn($timeZone); + $this->localeDateMock->expects($this->once()) ->method('date') ->with($defaultValue, null, false) ->willReturn($dateTimeMock); - $entityType->expects($this->any())->method('getEntityTypeCode')->willReturn('entity_type_code'); - $this->eavData->expects($this->any())->method('getFrontendClasses')->willReturn([]); - $formElement->expects($this->exactly(2))->method('setDisabled')->willReturnSelf(); - $this->yesNo->expects($this->any())->method('toOptionArray')->willReturn(['yes', 'no']); - $this->filesystem->expects($this->any())->method('getDirectoryRead')->willReturn($directoryReadInterface); - $directoryReadInterface->expects($this->any())->method('getRelativePath')->willReturn('relative_path'); - $this->propertyLocker->expects($this->once())->method('lock')->with($form); + $entityType->method('getEntityTypeCode')->willReturn('entity_type_code'); + $this->eavDataMock->method('getFrontendClasses')->willReturn([]); + $formElement->expects($this->exactly(3))->method('setDisabled')->willReturnSelf(); + $this->yesNoMock->method('toOptionArray')->willReturn(['yes', 'no']); + $this->filesystemMock->method('getDirectoryRead')->willReturn($directoryReadInterface); + $directoryReadInterface->method('getRelativePath')->willReturn('relative_path'); + $this->propertyLockerMock->expects($this->once())->method('lock')->with($form); $this->block->setData(['action' => 'save']); $this->block->toHtml(); diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php index 30d3503e4640e..a8b4e5f69e00e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php @@ -3,27 +3,30 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute; +use Magento\Backend\Model\View\Result\Redirect as ResultRedirect; use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save; -use Magento\Eav\Model\Validator\Attribute\Code as AttributeCodeValidator; -use Magento\Framework\Serialize\Serializer\FormData; -use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; -use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; +use Magento\Catalog\Helper\Product as ProductHelper; use Magento\Catalog\Model\Product\AttributeSet\Build; +use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; +use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; use Magento\Eav\Api\Data\AttributeSetInterface; +use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator as InputTypeValidator; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory; +use Magento\Eav\Model\Validator\Attribute\Code as AttributeCodeValidator; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Filter\FilterManager; -use Magento\Catalog\Helper\Product as ProductHelper; +use Magento\Framework\Serialize\Serializer\FormData; use Magento\Framework\View\Element\Messages; use Magento\Framework\View\LayoutFactory; -use Magento\Backend\Model\View\Result\Redirect as ResultRedirect; -use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator as InputTypeValidator; use Magento\Framework\View\LayoutInterface; +use PHPUnit\Framework\MockObject\MockObject; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -31,72 +34,72 @@ class SaveTest extends AttributeTest { /** - * @var BuildFactory|\PHPUnit_Framework_MockObject_MockObject + * @var BuildFactory|MockObject */ - protected $buildFactoryMock; + private $buildFactoryMock; /** - * @var FilterManager|\PHPUnit_Framework_MockObject_MockObject + * @var FilterManager|MockObject */ - protected $filterManagerMock; + private $filterManagerMock; /** - * @var ProductHelper|\PHPUnit_Framework_MockObject_MockObject + * @var ProductHelper|MockObject */ - protected $productHelperMock; + private $productHelperMock; /** - * @var AttributeFactory|\PHPUnit_Framework_MockObject_MockObject + * @var AttributeFactory|MockObject */ - protected $attributeFactoryMock; + private $attributeFactoryMock; /** - * @var ValidatorFactory|\PHPUnit_Framework_MockObject_MockObject + * @var ValidatorFactory|MockObject */ - protected $validatorFactoryMock; + private $validatorFactoryMock; /** - * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + * @var CollectionFactory|MockObject */ - protected $groupCollectionFactoryMock; + private $groupCollectionFactoryMock; /** - * @var LayoutFactory|\PHPUnit_Framework_MockObject_MockObject + * @var LayoutFactory|MockObject */ - protected $layoutFactoryMock; + private $layoutFactoryMock; /** - * @var ResultRedirect|\PHPUnit_Framework_MockObject_MockObject + * @var ResultRedirect|MockObject */ - protected $redirectMock; + private $redirectMock; /** - * @var AttributeSet|\PHPUnit_Framework_MockObject_MockObject + * @var AttributeSet|MockObject */ - protected $attributeSetMock; + private $attributeSetMock; /** - * @var Build|\PHPUnit_Framework_MockObject_MockObject + * @var Build|MockObject */ - protected $builderMock; + private $builderMock; /** - * @var InputTypeValidator|\PHPUnit_Framework_MockObject_MockObject + * @var InputTypeValidator|MockObject */ - protected $inputTypeValidatorMock; + private $inputTypeValidatorMock; /** - * @var FormData|\PHPUnit_Framework_MockObject_MockObject + * @var FormData|MockObject */ private $formDataSerializerMock; /** - * @var ProductAttributeInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ProductAttributeInterface|MockObject */ private $productAttributeMock; /** - * @var AttributeCodeValidator|\PHPUnit_Framework_MockObject_MockObject + * @var AttributeCodeValidator|MockObject */ private $attributeCodeValidatorMock; @@ -108,6 +111,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); $this->filterManagerMock = $this->getMockBuilder(FilterManager::class) + ->setMethods(['stripTags']) ->disableOriginalConstructor() ->getMock(); $this->productHelperMock = $this->getMockBuilder(ProductHelper::class) @@ -151,19 +155,16 @@ protected function setUp() ->setMethods(['getId', 'get']) ->getMockForAbstractClass(); - $this->buildFactoryMock->expects($this->any()) - ->method('create') + $this->buildFactoryMock->method('create') ->willReturn($this->builderMock); - $this->validatorFactoryMock->expects($this->any()) - ->method('create') + $this->validatorFactoryMock->method('create') ->willReturn($this->inputTypeValidatorMock); - $this->attributeFactoryMock - ->method('create') + $this->attributeFactoryMock->method('create') ->willReturn($this->productAttributeMock); } /** - * {@inheritdoc} + * @inheritDoc */ protected function getModel() { @@ -186,8 +187,7 @@ protected function getModel() public function testExecuteWithEmptyData() { - $this->requestMock->expects($this->any()) - ->method('getParam') + $this->requestMock->method('getParam') ->willReturnMap([ ['isAjax', null, null], ['serialized_options', '[]', ''], @@ -217,8 +217,7 @@ public function testExecute() 'frontend_input' => 'test_frontend_input', ]; - $this->requestMock->expects($this->any()) - ->method('getParam') + $this->requestMock->method('getParam') ->willReturnMap([ ['isAjax', null, null], ['serialized_options', '[]', ''], @@ -244,8 +243,7 @@ public function testExecute() $this->resultFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->redirectMock); - $this->redirectMock->expects($this->any()) - ->method('setPath') + $this->redirectMock->method('setPath') ->willReturnSelf(); $this->builderMock->expects($this->once()) ->method('setEntityTypeId') @@ -259,12 +257,14 @@ public function testExecute() $this->builderMock->expects($this->once()) ->method('getAttributeSet') ->willReturn($this->attributeSetMock); - $this->requestMock->expects($this->any()) - ->method('getParam') + $this->requestMock->method('getParam') ->willReturnMap([ ['set', null, 1], ['attribute_code', null, 'test_attribute_code'] ]); + $this->filterManagerMock->method('stripTags') + ->with($data['new_attribute_set_name']) + ->willReturn($data['new_attribute_set_name']); $this->inputTypeValidatorMock->expects($this->once()) ->method('getMessages') ->willReturn([]); @@ -279,10 +279,9 @@ public function testExecuteWithOptionsDataError() { $serializedOptions = '{"key":"value"}'; $message = "The attribute couldn't be saved due to an error. Verify your information and try again. " - . "If the error persists, please try again later."; + . 'If the error persists, please try again later.'; - $this->requestMock->expects($this->any()) - ->method('getParam') + $this->requestMock->method('getParam') ->willReturnMap([ ['isAjax', null, true], ['serialized_options', '[]', $serializedOptions], From 9ee0f6d4a1053bac33a849ea042e9e85756d0c14 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Thu, 24 Sep 2020 17:07:31 +0300 Subject: [PATCH 2/5] magento/magento2#21025: Missing "Apply To" when editing Product attributes - MFTF test added. --- ...ttributeAbsentOnProductFormActionGroup.xml | 21 +++++ ...tributePresentOnProductFormActionGroup.xml | 21 +++++ ...ctAttributeForSimpleProductActionGroup.xml | 20 +++++ .../AdvancedAttributePropertiesSection.xml | 6 ++ ...ProductAttributeEntityApplyToFieldTest.xml | 81 +++++++++++++++++++ 5 files changed, 149 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributeAbsentOnProductFormActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributePresentOnProductFormActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateProductAttributeForSimpleProductActionGroup.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributeAbsentOnProductFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributeAbsentOnProductFormActionGroup.xml new file mode 100644 index 0000000000000..930b97b6f9c3c --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributeAbsentOnProductFormActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Assert provided text Attribute is absent on the Product page. + + + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributePresentOnProductFormActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributePresentOnProductFormActionGroup.xml new file mode 100644 index 0000000000000..decbd6be950fd --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminTextAttributePresentOnProductFormActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + + Assert provided text Attribute is present on the Product page. + + + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateProductAttributeForSimpleProductActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateProductAttributeForSimpleProductActionGroup.xml new file mode 100644 index 0000000000000..0e2d838f04821 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/CreateProductAttributeForSimpleProductActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + EXTENDS: createProductAttribute. Fills in the Apply To with "Simple" value. + + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection/AdvancedAttributePropertiesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection/AdvancedAttributePropertiesSection.xml index bcd05e139d17c..8276196f8e69c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection/AdvancedAttributePropertiesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection/AdvancedAttributePropertiesSection.xml @@ -22,5 +22,11 @@ + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml new file mode 100644 index 0000000000000..1e431bca8db55 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml @@ -0,0 +1,81 @@ + + + + + + + + <description value="Check if 'Apply to' field on Product Attribute creation form works properly"/> + <severity value="AVERAGE"/> + <group value="Catalog"/> + </annotations> + + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="SimpleProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="VirtualProduct" stepKey="createVirtualProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + </before> + <after> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <deleteData createDataKey="createVirtualProduct" stepKey="deleteVirtualProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <actionGroup ref="DeleteAttributeSetByLabelActionGroup" stepKey="deleteCustomAttributeSet"> + <argument name="label" value="{{CatalogAttributeSet.attribute_set_name}}"/> + </actionGroup> + <actionGroup ref="NavigateToEditProductAttributeActionGroup" stepKey="goToEditPage"> + <argument name="ProductAttribute" value="{{textProductAttribute.attribute_code}}"/> + </actionGroup> + <click stepKey="clickDelete" selector="{{AttributePropertiesSection.DeleteAttribute}}"/> + <click stepKey="clickOk" selector="{{AttributeDeleteModalSection.confirm}}"/> + <waitForPageLoad stepKey="waitForDeletion"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--Navigate to Stores > Attributes > Product.--> + <actionGroup ref="AdminOpenProductAttributePageActionGroup" stepKey="goToProductAttributes"/> + + <!-- Create new Product Attribute for Simple products --> + <actionGroup ref="CreateProductAttributeForSimpleProductActionGroup" stepKey="createAttribute"> + <argument name="attribute" value="textProductAttribute"/> + </actionGroup> + + <!-- Add created attribute to Attribute Set --> + <actionGroup ref="AdminAddUnassignedAttributeToGroupActionGroup" stepKey="createCustomAttributeSet"> + <argument name="label" value="{{CatalogAttributeSet.attribute_set_name}}"/> + <argument name="secondOption" value="{{textProductAttribute.attribute_code}}"/> + </actionGroup> + + <!-- Check if Custom Attribute is applied for Simple product --> + <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="openSimpleProductPage"> + <argument name="productId" value="$$createSimpleProduct.id$$"/> + </actionGroup> + <actionGroup ref="AdminProductPageSelectAttributeSetActionGroup" stepKey="selectAttributeSetSimple"> + <argument name="attributeSetName" value="{{CatalogAttributeSet.attribute_set_name}}"/> + </actionGroup> + <actionGroup ref="AssertAdminTextAttributePresentOnProductFormActionGroup" stepKey="checkCustomAttributeSimpleProduct"> + <argument name="attributeCode" value="{{textProductAttribute.attribute_code}}"/> + </actionGroup> + + <!-- Check if Custom Attribute is not applied for Virtual product --> + <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="openVirtualProductPage"> + <argument name="productId" value="$$createVirtualProduct.id$$"/> + </actionGroup> + <actionGroup ref="AdminProductPageSelectAttributeSetActionGroup" stepKey="selectAttributeSetVirtual"> + <argument name="attributeSetName" value="{{CatalogAttributeSet.attribute_set_name}}"/> + </actionGroup> + <actionGroup ref="AssertAdminTextAttributeAbsentOnProductFormActionGroup" stepKey="checkCustomAttributeVirtualProduct"> + <argument name="attributeCode" value="{{textProductAttribute.attribute_code}}"/> + </actionGroup> + </test> +</tests> From 8145c94b7f5b0703355e67bc3f7b72f9d4c841d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= <bartlomiejszubert@gmail.com> Date: Sat, 26 Sep 2020 13:59:04 +0200 Subject: [PATCH 3/5] Fix #21025 - Added "Apply To" field to create attribute popup on product edit form --- .../ui_component/product_attribute_add_form.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml index 7f87eb0cdd391..e93a10442a4dc 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/product_attribute_add_form.xml @@ -516,6 +516,20 @@ </checkbox> </formElements> </field> + <field name="apply_to" sortOrder="80" formElement="multiselect"> + <settings> + <dataType>string</dataType> + <label translate="true">Apply To</label> + <dataScope>apply_to</dataScope> + </settings> + <formElements> + <multiselect> + <settings> + <options class="Magento\Catalog\Model\Attribute\Source\ApplyTo"/> + </settings> + </multiselect> + </formElements> + </field> </fieldset> <fieldset name="manage-titles" sortOrder="25"> <settings> From feaa19c5fad289f8d65039a260fbe1701e4d97fc Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky <engcom-vendorworker-foxtrot@adobe.com> Date: Mon, 28 Sep 2020 13:25:48 +0300 Subject: [PATCH 4/5] magento/magento2#21025: Missing "Apply To" when editing Product attributes - MFTF tests fix. --- .../CreateProductAttributeEntityApplyToFieldTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml index 1e431bca8db55..cc56b6eee5a3c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/CreateProductAttributeEntityTest/CreateProductAttributeEntityApplyToFieldTest.xml @@ -10,6 +10,7 @@ <test name="CreateProductAttributeEntityApplyToFieldTest"> <annotations> <features value="Catalog"/> + <stories value="Create Product Attributes"/> <title value="Create product attribute entity apply to field test"/> <description value="Check if 'Apply to' field on Product Attribute creation form works properly"/> <severity value="AVERAGE"/> From 8de29ee996e8369d8d0f2af54b4bf368a4ff98c6 Mon Sep 17 00:00:00 2001 From: engcom-Dash <grp-engcom-vendorworker-Dash@adobe.com> Date: Thu, 3 Oct 2024 17:47:47 +0530 Subject: [PATCH 5/5] 27625: Fix failed test --- .../Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php | 1 - .../Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php index 1ea14e5b36e9c..da044b309f6c7 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php @@ -30,7 +30,6 @@ class Advanced extends Generic { /** - * Eav data * * @var Data */ diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php index 5871bd9d007c3..8fd1b18848f27 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php @@ -138,7 +138,7 @@ protected function setUp(): void ->disableOriginalConstructor() ->getMock(); $this->filterManagerMock = $this->getMockBuilder(FilterManager::class) - ->setMethods(['stripTags']) + ->addMethods(['stripTags']) ->disableOriginalConstructor() ->getMock(); $this->productHelperMock = $this->getMockBuilder(ProductHelper::class) @@ -299,7 +299,7 @@ public function testExecute() 'frontend_input' => 'test_frontend_input', ]; - $this->filterManagerMock + $this->filterManagerMock->expects($this->once()) ->method('stripTags') ->willReturn('Test attribute set name'); $this->requestMock->expects($this->any())