diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php index 10722de41c1d2abfd788e9c492fd06d29c5c3273..2deb4800bd023b7290a65f2a7375a11a8214e75b 100755 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -9,6 +9,7 @@ use Magento\Catalog\Model\Product\Type; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav; use Magento\Eav\Model\Config; use Magento\Framework\App\RequestInterface; +use Magento\Framework\EntityManager\EventManager; use Magento\Store\Model\StoreManagerInterface; use Magento\Store\Api\Data\StoreInterface; use Magento\Ui\DataProvider\EavValidationRules; @@ -27,11 +28,15 @@ use Magento\Framework\Api\SortOrderBuilder; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\Framework\Api\SearchResultsInterface; use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Framework\Api\AttributeInterface; use Magento\Eav\Api\Data\AttributeGroupInterface; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Framework\Currency; use Magento\Framework\Locale\Currency as CurrencyLocale; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Stdlib\ArrayManager; +use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory as EavAttributeFactory; +use Magento\Framework\Event\ManagerInterface; /** * Class EavTest @@ -157,6 +162,26 @@ class EavTest extends AbstractModifierTest */ protected $currencyLocaleMock; + /** + * @var ProductAttributeInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productAttributeMock; + + /** + * @var ArrayManager|\PHPUnit_Framework_MockObject_MockObject + */ + protected $arrayManagerMock; + + /** + * @var EavAttributeFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eavAttributeFactoryMock; + + /** + * @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + /** * @var ObjectManager */ @@ -167,6 +192,9 @@ class EavTest extends AbstractModifierTest */ protected $eav; + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ protected function setUp() { parent::setUp(); @@ -228,10 +256,24 @@ class EavTest extends AbstractModifierTest $this->searchResultsMock = $this->getMockBuilder(SearchResultsInterface::class) ->getMockForAbstractClass(); $this->eavAttributeMock = $this->getMockBuilder(Attribute::class) - ->setMethods(['getAttributeGroupCode', 'getApplyTo', 'getFrontendInput', 'getAttributeCode']) + ->setMethods(['load', 'getAttributeGroupCode', 'getApplyTo', 'getFrontendInput', 'getAttributeCode']) + ->disableOriginalConstructor() + ->getMock(); + $this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class) + ->getMock(); + $this->arrayManagerMock = $this->getMockBuilder(ArrayManager::class) + ->getMock(); + $this->eavAttributeFactoryMock = $this->getMockBuilder(EavAttributeFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class) ->disableOriginalConstructor() ->getMock(); + $this->eavAttributeFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->eavAttributeMock); $this->groupCollectionFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->groupCollectionMock); @@ -277,6 +319,9 @@ class EavTest extends AbstractModifierTest ->disableOriginalConstructor() ->setMethods(['getCurrency']) ->getMock(); + $this->eavAttributeMock->expects($this->any()) + ->method('load') + ->willReturnSelf(); $this->eav =$this->getModel(); $this->objectManager->setBackwardCompatibleProperty( @@ -304,6 +349,9 @@ class EavTest extends AbstractModifierTest 'attributeGroupRepository' => $this->attributeGroupRepositoryMock, 'sortOrderBuilder' => $this->sortOrderBuilderMock, 'attributeRepository' => $this->attributeRepositoryMock, + 'arrayManager' => $this->arrayManagerMock, + 'eavAttributeFactory' => $this->eavAttributeFactoryMock, + '_eventManager' => $this->eventManagerMock ]); } @@ -399,4 +447,162 @@ class EavTest extends AbstractModifierTest $this->assertEquals($sourceData, $this->eav->modifyData([])); } + + /** + * @param int $productId + * @param bool $productRequired + * @param string $attrValue + * @param array $expected + * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::isProductExists + * @covers \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Eav::setupAttributeMeta + * @dataProvider setupAttributeMetaDataProvider + */ + public function testSetupAttributeMetaDefaultAttribute($productId, $productRequired, $attrValue, $expected) + { + $configPath = 'arguments/data/config'; + $groupCode = 'product-details'; + $sortOrder = '0'; + + $this->productMock->expects($this->any()) + ->method('getId') + ->willReturn($productId); + + $this->productAttributeMock->expects($this->any()) + ->method('getIsRequired') + ->willReturn($productRequired); + + $this->productAttributeMock->expects($this->any()) + ->method('getDefaultValue') + ->willReturn('required_value'); + + $this->productAttributeMock->expects($this->any()) + ->method('getAttributeCode') + ->willReturn('code'); + + $this->productAttributeMock->expects($this->any()) + ->method('getValue') + ->willReturn('value'); + + $attributeMock = $this->getMockBuilder(AttributeInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $attributeMock->expects($this->any()) + ->method('getValue') + ->willReturn($attrValue); + + $this->productMock->expects($this->any()) + ->method('getCustomAttribute') + ->willReturn($attributeMock); + + $this->arrayManagerMock->expects($this->any()) + ->method('set') + ->with( + $configPath, + [], + $expected + ) + ->willReturn($expected); + + $this->arrayManagerMock->expects($this->any()) + ->method('merge') + ->willReturn($expected); + + $this->arrayManagerMock->expects($this->any()) + ->method('get') + ->willReturn([]); + + $this->arrayManagerMock->expects($this->any()) + ->method('exists'); + + $this->assertEquals( + $expected, + $this->eav->setupAttributeMeta($this->productAttributeMock, $groupCode, $sortOrder) + ); + } + + /** + * @return array + */ + public function setupAttributeMetaDataProvider() + { + return [ + 'default_null_prod_not_new_and_required' => [ + 'productId' => 1, + 'productRequired' => true, + 'attrValue' => 'val', + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => true, + 'notice' => null, + 'default' => null, + 'label' => null, + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], + ], + 'default_null_prod_not_new_and_not_required' => [ + 'productId' => 1, + 'productRequired' => false, + 'attrValue' => 'val', + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => null, + 'label' => null, + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], + ], + 'default_null_prod_new_and_not_required' => [ + 'productId' => null, + 'productRequired' => false, + 'attrValue' => null, + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => 'required_value', + 'label' => null, + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], + ], + 'default_null_prod_new_and_required' => [ + 'productId' => null, + 'productRequired' => false, + 'attrValue' => null, + 'expected' => [ + 'dataType' => null, + 'formElement' => null, + 'visible' => null, + 'required' => false, + 'notice' => null, + 'default' => 'required_value', + 'label' => null, + 'code' => 'code', + 'source' => 'product-details', + 'scopeLabel' => '', + 'globalScope' => false, + 'sortOrder' => 0 + ], + ] + ]; + } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index edab28873b5b79bc2112a1b7de8e1c22956168c1..1419c17e11b298d1fcdc554a3131d7b8c9b8ffe8 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -522,6 +522,16 @@ class Eav extends AbstractModifier return $this->prevSetAttributes; } + /** + * Check is product already new or we trying to create one + * + * @return bool + */ + private function isProductExists() + { + return (bool) $this->locator->getProduct()->getId(); + } + /** * Initial meta setup * @@ -531,6 +541,7 @@ class Eav extends AbstractModifier * @return array * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) * @api */ public function setupAttributeMeta(ProductAttributeInterface $attribute, $groupCode, $sortOrder) @@ -543,7 +554,7 @@ class Eav extends AbstractModifier 'visible' => $attribute->getIsVisible(), 'required' => $attribute->getIsRequired(), 'notice' => $attribute->getNote(), - 'default' => $attribute->getDefaultValue(), + 'default' => (!$this->isProductExists()) ? $attribute->getDefaultValue() : null, 'label' => $attribute->getDefaultFrontendLabel(), 'code' => $attribute->getAttributeCode(), 'source' => $groupCode, diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index ebcbd96789588b30abd833bf3a9684181c9a83a9..1887639c8d0313fe466aadb89b3cdaf7adc6bd81 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -44,9 +44,9 @@ define([ if (_.isUndefined(caption)) { caption = node.label; } - } else { - return node; } + + return node; }); return { @@ -194,7 +194,7 @@ define([ }, /** - * Matches specfied value with existing options + * Matches specified value with existing options * or, if value is not specified, returns value of the first option. * * @returns {*} @@ -286,6 +286,11 @@ define([ return preview; }, + /** + * + * @param {Number} value + * @returns {Object} Chainable + */ getOption: function (value) { return this.indexedOptions[value]; }, @@ -301,6 +306,19 @@ define([ this.value(value); return this; + }, + + /** + * Initializes observable properties of instance + * + * @returns {Object} Chainable. + */ + setInitialValue: function () { + if (_.isUndefined(this.value()) && !this.default) { + this.clear(); + } + + return this._super(); } }); }); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/EavTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/EavTest.php index ffcf5096b103f74c7406e4a36eeba22115090ac0..eeba8d78cead15a0d444c5cedd24f5ee5b18f7c1 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/EavTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/EavTest.php @@ -70,6 +70,19 @@ class EavTest extends \PHPUnit_Framework_TestCase $this->prepareDataForComparison($actualMeta, $expectedMeta); $this->assertEquals($expectedMeta, $actualMeta); } + + public function testModifyMetaNewProduct() + { + $this->objectManager->get(\Magento\Eav\Model\Entity\AttributeCache::class)->clear(); + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class); + $product->setAttributeSetId(4); + $this->locatorMock->expects($this->any())->method('getProduct')->willReturn($product); + $expectedMeta = include __DIR__ . '/_files/eav_expected_meta_output_w_default.php'; + $actualMeta = $this->eavModifier->modifyMeta([]); + $this->prepareDataForComparison($actualMeta, $expectedMeta); + $this->assertEquals($expectedMeta, $actualMeta); + } /** * @magentoDataFixture Magento/Catalog/_files/product_simple_with_admin_store.php diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output.php index 1f22ec3b1c6ebcc9a1f4cef384d9d0ac9e875f65..29b092177b522efdebe0cc53e507225493da81c8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output.php @@ -35,7 +35,6 @@ return [ "visible" => "1", "required" => "0", "label" => "Enable Product", - "default" => "1", "source" => "product-details", "scopeLabel" => "[WEBSITE]", "globalScope" => false, diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output_w_default.php b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output_w_default.php new file mode 100644 index 0000000000000000000000000000000000000000..999a96d29811ff68fe3dbbea152a02c56dee03fb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/_files/eav_expected_meta_output_w_default.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +return [ + "product-details" => [ + "arguments" => [ + "data" => [ + "config" => [ + "dataScope" => "data.product", + ], + ], + ], + "children" => [ + "container_status" => [ + "children" => [ + "status" => [ + "arguments" => [ + "data" => [ + "config" => [ + "dataType" => "select", + "formElement" => "select", + "options" => [ + [ + "value" => 1, + "label" => "Enabled" + ], + [ + "value" => 2, + "label" => "Disabled" + ] + ], + "visible" => "1", + "required" => "0", + "label" => "Enable Product", + "default" => "1", + "source" => "product-details", + "scopeLabel" => "[WEBSITE]", + "globalScope" => false, + "code" => "status", + "sortOrder" => "__placeholder__", + "componentType" => "field" + ], + ], + ], + ], + ], + ], + "container_name" => [ + "children" => [ + "name" => [ + "arguments" => [ + "data" => [ + "config" => [ + "dataType" => "text", + "formElement" => "input", + "visible" => "1", + "required" => "1", + "label" => "Product Name", + "source" => "product-details", + "scopeLabel" => "[STORE VIEW]", + "globalScope" => false, + "code" => "name", + "sortOrder" => "__placeholder__", + "componentType" => "field", + "validation" => [ + "required-entry" => true + ], + ], + ], + ], + ], + ], + ], + "container_sku" => [ + "children" => [ + "sku" => [ + "arguments" => [ + "data" => [ + "config" => [ + "dataType" => "text", + "formElement" => "input", + "visible" => "1", + "required" => "1", + "label" => "SKU", + "source" => "product-details", + "scopeLabel" => "[GLOBAL]", + "globalScope" => true, + "code" => "sku", + "sortOrder" => "__placeholder__", + "componentType" => "field", + "validation" => [ + "required-entry" => true + ], + ], + ], + ], + ], + ], + ], + ], + ], +];