Skip to content

Commit

Permalink
Showing 30 changed files with 542 additions and 36 deletions.
34 changes: 31 additions & 3 deletions app/code/Magento/Catalog/Block/Adminhtml/Category/Tree.php
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ public function __construct(
}

/**
* @return void
* @inheritdoc
*/
protected function _construct()
{
@@ -80,7 +80,7 @@ protected function _construct()
}

/**
* @return $this
* @inheritdoc
*/
protected function _prepareLayout()
{
@@ -182,6 +182,8 @@ public function getSuggestedCategoriesJson($namePart)
}

/**
* Get add root button html
*
* @return string
*/
public function getAddRootButtonHtml()
@@ -190,6 +192,8 @@ public function getAddRootButtonHtml()
}

/**
* Get add sub button html
*
* @return string
*/
public function getAddSubButtonHtml()
@@ -198,6 +202,8 @@ public function getAddSubButtonHtml()
}

/**
* Get expand button html
*
* @return string
*/
public function getExpandButtonHtml()
@@ -206,6 +212,8 @@ public function getExpandButtonHtml()
}

/**
* Get collapse button html
*
* @return string
*/
public function getCollapseButtonHtml()
@@ -214,6 +222,8 @@ public function getCollapseButtonHtml()
}

/**
* Get store switcher
*
* @return string
*/
public function getStoreSwitcherHtml()
@@ -222,6 +232,8 @@ public function getStoreSwitcherHtml()
}

/**
* Get loader tree url
*
* @param bool|null $expanded
* @return string
*/
@@ -235,6 +247,8 @@ public function getLoadTreeUrl($expanded = null)
}

/**
* Get nodes url
*
* @return string
*/
public function getNodesUrl()
@@ -243,6 +257,8 @@ public function getNodesUrl()
}

/**
* Get switcher tree url
*
* @return string
*/
public function getSwitchTreeUrl()
@@ -254,6 +270,8 @@ public function getSwitchTreeUrl()
}

/**
* Get is was expanded
*
* @return bool
* @SuppressWarnings(PHPMD.BooleanGetMethodName)
*/
@@ -263,6 +281,8 @@ public function getIsWasExpanded()
}

/**
* Get move url
*
* @return string
*/
public function getMoveUrl()
@@ -271,6 +291,8 @@ public function getMoveUrl()
}

/**
* Get tree
*
* @param mixed|null $parenNodeCategory
* @return array
*/
@@ -282,6 +304,8 @@ public function getTree($parenNodeCategory = null)
}

/**
* Get tree json
*
* @param mixed|null $parenNodeCategory
* @return string
*/
@@ -367,7 +391,7 @@ protected function _getNodeJson($node, $level = 0)
}
}

if ($isParent || $node->getLevel() < 2) {
if ($isParent || $node->getLevel() < 1) {
$item['expanded'] = true;
}

@@ -390,6 +414,8 @@ public function buildNodeName($node)
}

/**
* Is category movable
*
* @param Node|array $node
* @return bool
*/
@@ -403,6 +429,8 @@ protected function _isCategoryMoveable($node)
}

/**
* Is parent selected category
*
* @param Node|array $node
* @return bool
*/
23 changes: 20 additions & 3 deletions app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Catalog\Model\Product\Option;

use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface as OptionRepository;
@@ -58,11 +60,26 @@ public function execute($entity, $arguments = [])
}
}
if ($options) {
foreach ($options as $option) {
$this->optionRepository->save($option);
}
$this->processOptionsSaving($options, (bool)$entity->dataHasChangedFor('sku'), (string)$entity->getSku());
}

return $entity;
}

/**
* Save custom options
*
* @param array $options
* @param bool $hasChangedSku
* @param string $newSku
*/
private function processOptionsSaving(array $options, bool $hasChangedSku, string $newSku)
{
foreach ($options as $option) {
if ($hasChangedSku && $option->hasData('product_sku')) {
$option->setProductSku($newSku);
}
$this->optionRepository->save($option);
}
}
}
Original file line number Diff line number Diff line change
@@ -52,4 +52,51 @@
<selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType('0')}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/>
<fillField selector="{{AdminProductCustomizableOptionsSection.optionFileExtensions('0')}}" userInput="{{option.file_extension}}" stepKey="fillCompatibleExtensions"/>
</actionGroup>
<actionGroup name="AddProductCustomOptionField">
<arguments>
<argument name="option" defaultValue="ProductOptionField"/>
<argiment name="optionIndex" type="string"/>
</arguments>
<conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/>
<click selector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" stepKey="clickAddOption"/>
<waitForElementVisible selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" stepKey="waitForOption"/>
<fillField selector="{{AdminProductCustomizableOptionsSection.lastOptionTitle}}" userInput="{{option.title}}" stepKey="fillTitle"/>
<click selector="{{AdminProductCustomizableOptionsSection.lastOptionTypeParent}}" stepKey="openTypeSelect"/>
<click selector="{{AdminProductCustomizableOptionsSection.optionType('Field')}}" stepKey="selectTypeFile"/>
<waitForElementVisible selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" stepKey="waitForElements"/>
<fillField selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" userInput="{{option.price}}" stepKey="fillPrice"/>
<selectOption selector="{{AdminProductCustomizableOptionsSection.optionPriceType(optionIndex)}}" userInput="{{option.price_type}}" stepKey="selectPriceType"/>
<fillField selector="{{AdminProductCustomizableOptionsSection.optionSku(optionIndex)}}" userInput="{{option.title}}" stepKey="fillSku"/>
</actionGroup>
<actionGroup name="importProductCustomizableOptions">
<arguments>
<argument name="productName" type="string"/>
</arguments>
<click selector="{{AdminProductCustomizableOptionsSection.importOptions}}" stepKey="clickImportOptions"/>
<waitForElementVisible selector="{{AdminProductImportOptionsSection.selectProductTitle}}" stepKey="waitForTitleVisible"/>
<conditionalClick selector="{{AdminProductImportOptionsSection.resetFiltersButton}}" dependentSelector="{{AdminProductImportOptionsSection.resetFiltersButton}}" visible="true" stepKey="clickResetFilters"/>
<click selector="{{AdminProductImportOptionsSection.filterButton}}" stepKey="clickFilterButton"/>
<waitForElementVisible selector="{{AdminProductImportOptionsSection.nameField}}" stepKey="waitForNameField"/>
<fillField selector="{{AdminProductImportOptionsSection.nameField}}" userInput="{{productName}}" stepKey="fillProductName"/>
<click selector="{{AdminProductImportOptionsSection.applyFiltersButton}}" stepKey="clickApplyFilters"/>
<checkOption selector="{{AdminProductImportOptionsSection.firstRowItemCheckbox}}" stepKey="checkProductCheckbox"/>
<click selector="{{AdminProductImportOptionsSection.importButton}}" stepKey="clickImport"/>
</actionGroup>
<actionGroup name="resetImportOptionFilter">
<conditionalClick selector="{{AdminProductCustomizableOptionsSection.customizableOptions}}" dependentSelector="{{AdminProductCustomizableOptionsSection.addOptionBtn}}" visible="false" stepKey="openCustomOptionSection"/>
<click selector="{{AdminProductCustomizableOptionsSection.importOptions}}" stepKey="clickImportOptions"/>
<click selector="{{AdminProductImportOptionsSection.resetFiltersButton}}" stepKey="clickResetFilterButton"/>
</actionGroup>
<actionGroup name="checkCustomizableOptionImport">
<arguments>
<argument name="option" defaultValue="ProductOptionField"/>
<argiment name="optionIndex" type="string"/>
</arguments>
<grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionTitleInput(optionIndex)}}" stepKey="grabOptionTitle"/>
<grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionPrice(optionIndex)}}" stepKey="grabOptionPrice"/>
<grabValueFrom selector="{{AdminProductCustomizableOptionsSection.optionSku(optionIndex)}}" stepKey="grabOptionSku"/>
<assertEquals expected="{{option.title}}" expectedType="string" actual="$grabOptionTitle" stepKey="assertOptionTitle"/>
<assertEquals expected="{{option.price}}" expectedType="string" actual="$grabOptionPrice" stepKey="assertOptionPrice"/>
<assertEquals expected="{{option.title}}" expectedType="string" actual="$grabOptionSku" stepKey="assertOptionSku"/>
</actionGroup>
</actionGroups>
4 changes: 4 additions & 0 deletions app/code/Magento/Catalog/Test/Mftf/Data/ConstData.xml
Original file line number Diff line number Diff line change
@@ -13,4 +13,8 @@
<data key="one">1</data>
<data key="two">2</data>
</entity>
<entity name="prodNameWithSpecChars">
<data key="trademark">"Pursuit Lumaflex™ Tone Band"</data>
<data key="skumark">"x™"</data>
</entity>
</entities>
4 changes: 4 additions & 0 deletions app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
Original file line number Diff line number Diff line change
@@ -35,6 +35,10 @@
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
</entity>
<entity name="ApiSimpleProductWithSpecCharInName" type="product" extends="ApiSimpleProduct">
<data key="name">Pursuit Lumaflex&#38;trade; Tone Band</data>
<data key="sku" unique="suffix">x&#38;trade;</data>
</entity>
<entity name="ApiSimpleProductWithCustomPrice" type="product" extends="ApiSimpleProduct">
<data key="price">100</data>
</entity>
Original file line number Diff line number Diff line change
@@ -16,5 +16,6 @@
<element name="categoryInTreeUnderRoot" type="text" selector="//li/ul/li[@class='x-tree-node']/div/a/span[contains(text(), '{{name}}')]" parameterized="true"/>
<element name="lastCreatedCategory" type="block" selector=".x-tree-root-ct li li:last-child" />
<element name="treeContainer" type="block" selector=".tree-holder" />
<element name="expandRootCategory" type="text" selector="img.x-tree-elbow-end-plus"/>
</section>
</sections>
Original file line number Diff line number Diff line change
@@ -45,5 +45,15 @@
<element name="optionPriceType" type="select" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr//*[@name='product[options][{{var}}][price_type]']" parameterized="true"/>
<element name="optionSku" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr//*[@name='product[options][{{index}}][sku]']" parameterized="true"/>
<element name="optionFileExtensions" type="input" selector="//*[@data-index='custom_options']//*[@data-index='options']/tbody/tr//*[@name='product[options][{{index}}][file_extension]']" parameterized="true"/>
<element name="importOptions" type="button" selector="//button[@data-index='button_import']" timeout="30"/>
</section>
</sections>
<section name="AdminProductImportOptionsSection">
<element name="selectProductTitle" type="text" selector="//h1[contains(text(), 'Select Product')]" timeout="30"/>
<element name="filterButton" type="button" selector="//button[@data-action='grid-filter-expand']" timeout="30"/>
<element name="nameField" type="input" selector="//input[@name='name']" timeout="30"/>
<element name="applyFiltersButton" type="button" selector="//button[@data-action='grid-filter-apply']" timeout="30"/>
<element name="resetFiltersButton" type="button" selector="//button[@data-action='grid-filter-reset']" timeout="30"/>
<element name="firstRowItemCheckbox" type="input" selector="//input[@data-action='select-row']" timeout="30"/>
<element name="importButton" type="button" selector="//button[contains(@class, 'action-primary')]/span[contains(text(), 'Import')]" timeout="30"/>
</section>
</sections>
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
<element name="productGridElement2" type="text" selector="#addselector" />
<element name="productGridRows" type="text" selector="table.data-grid tr.data-row"/>
<element name="firstProductRow" type="text" selector="table.data-grid tr.data-row:first-of-type"/>
<element name="firstProductRowName" type="text" selector="table.data-grid tr.data-row:first-of-type > td:nth-of-type(4)"/>
<element name="firstProductRowEditButton" type="button" selector="table.data-grid tr.data-row td .action-menu-item:first-of-type"/>
<element name="productThumbnail" type="text" selector="table.data-grid tr:nth-child({{row}}) td.data-grid-thumbnail-cell > img" parameterized="true"/>
<element name="productThumbnailBySrc" type="text" selector="img.admin__control-thumbnail[src*='{{pattern}}']" parameterized="true"/>
Original file line number Diff line number Diff line change
@@ -12,5 +12,6 @@
<element name="subCategory" type="button" selector="//ul[contains(@class,'submenu')]//span[contains(text(),'{{var1}}')]" parameterized="true"/>
<element name="breadcrumbs" type="textarea" selector=".items"/>
<element name="categoryBreadcrumbs" type="textarea" selector=".breadcrumbs li"/>
<element name="categoryBreadcrumbsByNumber" type="textarea" selector=".breadcrumbs li:nth-of-type({{number}})" parameterized="true"/>
</section>
</sections>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="AdminFilterByNameByStoreViewOnProductGridTest">
<annotations>
<features value="Catalog"/>
<stories value="Filter products"/>
<title value="Product grid filtering by store view level attribute"/>
<description value="Verify that products grid can be filtered on all store view level by attribute"/>
<severity value="MAJOR"/>
<testCaseId value="MAGETWO-98755"/>
<useCaseId value="MAGETWO-98335"/>
<group value="catalog"/>
</annotations>
<before>
<createData entity="SimpleProduct2" stepKey="createSimpleProduct"/>
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
</before>
<after>
<deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/>
<actionGroup ref="ClearProductsFilterActionGroup" stepKey="clearProductsFilter"/>
<actionGroup ref="logout" stepKey="logout"/>
</after>
<amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="goToEditPage"/>
<actionGroup ref="AdminSwitchStoreViewActionGroup" stepKey="switchToDefaultStoreView">
<argument name="storeView" value="_defaultStore.name"/>
</actionGroup>
<scrollToTopOfPage stepKey="scrollToTopOfAdminProductFormSection"/>
<click selector="{{AdminProductFormSection.productNameUseDefault}}" stepKey="uncheckUseDefault"/>
<fillField selector="{{AdminProductFormSection.productName}}" userInput="{{SimpleProduct.name}}" stepKey="fillNewName"/>
<actionGroup ref="saveProductForm" stepKey="saveSimpleProduct"/>
<amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/>
<actionGroup ref="filterProductGridByName" stepKey="filterGridByName">
<argument name="product" value="SimpleProduct"/>
</actionGroup>
<see selector="{{AdminProductGridSection.firstProductRow}}" userInput="{{SimpleProduct2.name}}" stepKey="seeProductNameInGrid"/>
</test>
</tests>
Loading

0 comments on commit 86fb020

Please sign in to comment.