diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginSuccessfulTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginSuccessfulTest.xml index 7bb249e974c3..73b14bdc1415 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginSuccessfulTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginSuccessfulTest.xml @@ -19,8 +19,6 @@ - - diff --git a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/SetBundleProductAttributesActionGroup.xml b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/SetBundleProductAttributesActionGroup.xml index b940dfac865d..a58baac6f6b3 100644 --- a/app/code/Magento/Bundle/Test/Mftf/ActionGroup/SetBundleProductAttributesActionGroup.xml +++ b/app/code/Magento/Bundle/Test/Mftf/ActionGroup/SetBundleProductAttributesActionGroup.xml @@ -60,6 +60,7 @@ + diff --git a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml index b51b3d348cce..8b78ac7b5fe6 100644 --- a/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml +++ b/app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml @@ -124,5 +124,6 @@ + diff --git a/app/code/Magento/Catalog/Model/Category/AttributeRepository.php b/app/code/Magento/Catalog/Model/Category/AttributeRepository.php index 3243bf718e66..65443e223e85 100644 --- a/app/code/Magento/Catalog/Model/Category/AttributeRepository.php +++ b/app/code/Magento/Catalog/Model/Category/AttributeRepository.php @@ -29,6 +29,11 @@ class AttributeRepository implements CategoryAttributeRepositoryInterface */ private $eavConfig; + /** + * @var array + */ + private $metadataCache; + /** * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder * @param \Magento\Framework\Api\FilterBuilder $filterBuilder @@ -48,7 +53,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria) { @@ -59,7 +64,7 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr } /** - * {@inheritdoc} + * @inheritdoc */ public function get($attributeCode) { @@ -70,23 +75,27 @@ public function get($attributeCode) } /** - * {@inheritdoc} + * @inheritdoc + * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function getCustomAttributesMetadata($dataObjectClassName = null) { - $defaultAttributeSetId = $this->eavConfig - ->getEntityType(\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE) - ->getDefaultAttributeSetId(); - $searchCriteria = $this->searchCriteriaBuilder->addFilters( - [ - $this->filterBuilder - ->setField('attribute_set_id') - ->setValue($defaultAttributeSetId) - ->create(), - ] - ); - - return $this->getList($searchCriteria->create())->getItems(); + if (!isset($this->metadataCache[$dataObjectClassName])) { + $defaultAttributeSetId = $this->eavConfig + ->getEntityType(\Magento\Catalog\Api\Data\CategoryAttributeInterface::ENTITY_TYPE_CODE) + ->getDefaultAttributeSetId(); + $searchCriteria = $this->searchCriteriaBuilder->addFilters( + [ + $this->filterBuilder + ->setField('attribute_set_id') + ->setValue($defaultAttributeSetId) + ->create(), + ] + ); + $this->metadataCache[$dataObjectClassName] = $this->getList($searchCriteria->create()) + ->getItems(); + } + return $this->metadataCache[$dataObjectClassName]; } } diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml index 408669f29f1b..526ac700a0b5 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryMainSection.xml @@ -43,5 +43,6 @@ + diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryTopToolbarSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryTopToolbarSection.xml index e063b5fc8c1b..2c340add2626 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryTopToolbarSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryTopToolbarSection.xml @@ -14,5 +14,6 @@ + diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeCategoryDisplaySettingsOnStorefrontTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeCategoryDisplaySettingsOnStorefrontTest.xml new file mode 100644 index 000000000000..ec26e65c0678 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminChangeCategoryDisplaySettingsOnStorefrontTest.xml @@ -0,0 +1,138 @@ + + + + + + + + + <description value="Verify correctness of Sorting, Navigation, Listing products at the Storefront Category"/> + <severity value="MAJOR"/> + <testCaseId value="AC-4150"/> + <group value="Catalog"/> + </annotations> + <before> + <!-- create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <!-- create 11 simple products --> + <createData entity="SimpleProduct" stepKey="createSimpleProduct1"> + <field key="price">10</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct2"> + <field key="price">11</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct3"> + <field key="price">12</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct4"> + <field key="price">13</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct5"> + <field key="price">14</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct6"> + <field key="price">15</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct7"> + <field key="price">16</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct8"> + <field key="price">17</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct9"> + <field key="price">18</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct10"> + <field key="price">19</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct11"> + <field key="price">20</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="SimpleProduct" stepKey="createSimpleProduct12"> + <field key="price">21</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData><createData entity="SimpleProduct" stepKey="createSimpleProduct13"> + <field key="price">22</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData><createData entity="SimpleProduct" stepKey="createSimpleProduct14"> + <field key="price">23</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData><createData entity="SimpleProduct" stepKey="createSimpleProduct15"> + <field key="price">24</field> + <field key="quantity">1000</field> + <requiredEntity createDataKey="createCategory"/> + </createData> + </before> + <after> + <!-- delete created entities --> + <deleteData createDataKey="createSimpleProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="createSimpleProduct2" stepKey="deleteSimpleProduct2"/> + <deleteData createDataKey="createSimpleProduct3" stepKey="deleteSimpleProduct3"/> + <deleteData createDataKey="createSimpleProduct4" stepKey="deleteSimpleProduct4"/> + <deleteData createDataKey="createSimpleProduct5" stepKey="deleteSimpleProduct5"/> + <deleteData createDataKey="createSimpleProduct6" stepKey="deleteSimpleProduct6"/> + <deleteData createDataKey="createSimpleProduct7" stepKey="deleteSimpleProduct7"/> + <deleteData createDataKey="createSimpleProduct8" stepKey="deleteSimpleProduct8"/> + <deleteData createDataKey="createSimpleProduct9" stepKey="deleteSimpleProduct9"/> + <deleteData createDataKey="createSimpleProduct10" stepKey="deleteSimpleProduct10"/> + <deleteData createDataKey="createSimpleProduct11" stepKey="deleteSimpleProduct11"/> + <deleteData createDataKey="createSimpleProduct12" stepKey="deleteSimpleProduct12"/> + <deleteData createDataKey="createSimpleProduct13" stepKey="deleteSimpleProduct13"/> + <deleteData createDataKey="createSimpleProduct14" stepKey="deleteSimpleProduct14"/> + <deleteData createDataKey="createSimpleProduct15" stepKey="deleteSimpleProduct15"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + <!-- Login to Admin page --> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AssertAdminSuccessLoginActionGroup" stepKey="assertLoggedIn"/> + <!-- Open created category on Storefront --> + <actionGroup ref="StorefrontGoToCategoryPageActionGroup" stepKey="openCategoryPage"> + <argument name="categoryName" value="$$createCategory.name$$"/> + </actionGroup> + <!-- Switch category view to List mode --> + <actionGroup ref="StorefrontSwitchCategoryViewToListModeActionGroup" stepKey="switchCategoryViewToListMode"/> + <!-- Sort products By Price --> + <actionGroup ref="StorefrontCategoryPageSortProductActionGroup" stepKey="sortProductByPrice"/> + <!-- Set Ascending Direction --> + <actionGroup ref="StorefrontCategoryPageSortAscendingActionGroup" stepKey="setAscendingDirection"/> + <!-- Sort products By ProductName --> + <selectOption selector="{{StorefrontCategoryTopToolbarSection.sortByDropdown}}" userInput="Product Name" stepKey="selectSortByProductName"/> + <!-- Set Descending Direction --> + <actionGroup ref="StorefrontCategoryPageSortDescendingActionGroup" stepKey="setDescendingDirection"/> + <selectOption selector="{{StorefrontCategoryTopToolbarSection.showDropdown}}" userInput="15" stepKey="selectShowProducts"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </test> +</tests> + + diff --git a/app/code/Magento/CatalogGraphQl/Model/Category/CategoryFilter.php b/app/code/Magento/CatalogGraphQl/Model/Category/CategoryFilter.php index 4350b6dd8526..d8b90b454b4a 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Category/CategoryFilter.php +++ b/app/code/Magento/CatalogGraphQl/Model/Category/CategoryFilter.php @@ -7,13 +7,11 @@ namespace Magento\CatalogGraphQl\Model\Category; -use Magento\Catalog\Api\CategoryRepositoryInterface; -use Magento\Catalog\Api\Data\CategorySearchResultsInterface; -use Magento\Catalog\Api\Data\CategorySearchResultsInterfaceFactory; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; use Magento\CatalogGraphQl\Model\Resolver\Categories\DataProvider\Category\CollectionProcessorInterface; use Magento\CatalogGraphQl\Model\Category\Filter\SearchCriteria; use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; +use Magento\Framework\DB\Select; use Magento\Framework\Exception\InputException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\GraphQl\Model\Query\ContextInterface; @@ -39,16 +37,6 @@ class CategoryFilter */ private $extensionAttributesJoinProcessor; - /** - * @var CategorySearchResultsInterfaceFactory - */ - private $categorySearchResultsFactory; - - /** - * @var CategoryRepositoryInterface - */ - private $categoryRepository; - /** * @var SearchCriteria */ @@ -58,23 +46,17 @@ class CategoryFilter * @param CollectionFactory $categoryCollectionFactory * @param CollectionProcessorInterface $collectionProcessor * @param JoinProcessorInterface $extensionAttributesJoinProcessor - * @param CategorySearchResultsInterfaceFactory $categorySearchResultsFactory - * @param CategoryRepositoryInterface $categoryRepository * @param SearchCriteria $searchCriteria */ public function __construct( CollectionFactory $categoryCollectionFactory, CollectionProcessorInterface $collectionProcessor, JoinProcessorInterface $extensionAttributesJoinProcessor, - CategorySearchResultsInterfaceFactory $categorySearchResultsFactory, - CategoryRepositoryInterface $categoryRepository, SearchCriteria $searchCriteria ) { $this->categoryCollectionFactory = $categoryCollectionFactory; $this->collectionProcessor = $collectionProcessor; $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor; - $this->categorySearchResultsFactory = $categorySearchResultsFactory; - $this->categoryRepository = $categoryRepository; $this->searchCriteria = $searchCriteria; } @@ -95,22 +77,21 @@ public function getResult(array $criteria, StoreInterface $store, array $attribu $this->extensionAttributesJoinProcessor->process($collection); $this->collectionProcessor->process($collection, $searchCriteria, $attributeNames, $context); - /** @var CategorySearchResultsInterface $searchResult */ - $categories = $this->categorySearchResultsFactory->create(); - $categories->setSearchCriteria($searchCriteria); - $categories->setItems($collection->getItems()); - $categories->setTotalCount($collection->getSize()); + // only fetch necessary category entity id + $collection + ->getSelect() + ->reset(Select::COLUMNS) + ->columns( + 'e.entity_id' + ); - $categoryIds = []; - foreach ($categories->getItems() as $category) { - $categoryIds[] = (int)$category->getId(); - } + $categoryIds = $collection->load()->getLoadedIds(); $totalPages = 0; - if ($categories->getTotalCount() > 0 && $searchCriteria->getPageSize() > 0) { - $totalPages = ceil($categories->getTotalCount() / $searchCriteria->getPageSize()); + if ($collection->getSize() > 0 && $searchCriteria->getPageSize() > 0) { + $totalPages = ceil($collection->getSize() / $searchCriteria->getPageSize()); } - if ($searchCriteria->getCurrentPage() > $totalPages && $categories->getTotalCount() > 0) { + if ($searchCriteria->getCurrentPage() > $totalPages && $collection->getSize() > 0) { throw new GraphQlInputException( __( 'currentPage value %1 specified is greater than the %2 page(s) available.', @@ -121,7 +102,7 @@ public function getResult(array $criteria, StoreInterface $store, array $attribu return [ 'category_ids' => $categoryIds, - 'total_count' => $categories->getTotalCount(), + 'total_count' => $collection->getSize(), 'page_info' => [ 'total_pages' => $totalPages, 'page_size' => $searchCriteria->getPageSize(), diff --git a/app/code/Magento/CatalogGraphQl/Model/Category/Hydrator.php b/app/code/Magento/CatalogGraphQl/Model/Category/Hydrator.php index 675118b95310..fc234c1de4e4 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Category/Hydrator.php +++ b/app/code/Magento/CatalogGraphQl/Model/Category/Hydrator.php @@ -60,8 +60,12 @@ public function hydrateCategory(Category $category, $basicFieldsOnly = false) : if ($basicFieldsOnly) { $categoryData = $category->getData(); } else { - $categoryData = $this->dataObjectProcessor->buildOutputDataArray($category, CategoryInterface::class); + $categoryData = $this->dataObjectProcessor->buildOutputDataArray( + $category, + CategoryInterface::class + ); } + $categoryData['id'] = $category->getId(); $categoryData['uid'] = $this->uidEncoder->encode((string) $category->getId()); $categoryData['children'] = []; diff --git a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml index 369f4bfb2303..0e0fa9d95580 100644 --- a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml @@ -191,6 +191,11 @@ <type name="Magento\Catalog\Api\ProductRepositoryInterface"> <plugin name="availableProductsFilter" type="Magento\CatalogGraphQl\Plugin\AvailableProductsFilter" /> </type> + <type name="Magento\CatalogGraphQl\Model\Category\Hydrator"> + <arguments> + <argument name="dataObjectProcessor" xsi:type="object">Magento\CatalogGraphQl\Category\DataObjectProcessor</argument> + </arguments> + </type> <virtualType name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ChildProduct" type="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product"> <arguments> @@ -207,4 +212,16 @@ </argument> </arguments> </virtualType> + <virtualType + name="Magento\CatalogGraphQl\Category\DataObjectProcessor" + type="Magento\Framework\Reflection\DataObjectProcessor" + > + <arguments> + <argument name="excludedMethodsClassMap" xsi:type="array"> + <item name="Magento\Catalog\Api\Data\CategoryInterface" xsi:type="array"> + <item name="getChildren" xsi:type="string">getChildren</item> + </item> + </argument> + </arguments> + </virtualType> </config> diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Test/StoreFrontAddOutOfStockProductToShoppingCartTest.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Test/StoreFrontAddOutOfStockProductToShoppingCartTest.xml new file mode 100644 index 000000000000..951ca2b0ee80 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Test/StoreFrontAddOutOfStockProductToShoppingCartTest.xml @@ -0,0 +1,70 @@ +<?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="StoreFrontAddOutOfStockProductToShoppingCartTest"> + <annotations> + <features value="[Disabled Inventory Check] Add Out of Stock Product to the Shopping Cart"/> + <stories value="[Disabled Inventory Check] Add Out of Stock Product to the Shopping Cart"/> + <title value="Checking Add Out of Stock Products to the Shopping Cart"/> + <description value="Placing the order for out of stock products and zero quantity"/> + <severity value="CRITICAL"/> + <testCaseId value="AC-5262"/> + </annotations> + + <before> + <!-- Set Enable Inventory Check On Cart Load = No --> + <magentoCLI command="config:set {{DisableInventoryCheckOnCartLoad.path}} {{DisableInventoryCheckOnCartLoad.value}}" stepKey="disableCartLoad"/> + <!-- Create default category with subcategory --> + <createData entity="ApiCategory" stepKey="createCategory"/> + <createData entity="SubCategoryWithParent" stepKey="createSubcategory"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <!-- Create SimpleProductwithPrice100 --> + <createData entity="SimpleProductQty100" stepKey="simpleProductOne"> + <requiredEntity createDataKey="createSubcategory"/> + </createData> + <!-- Go To Subcategory Page--> + <actionGroup ref="StorefrontGoToSubCategoryPageActionGroup" stepKey="goToCategoryC"> + <argument name="categoryName" value="$$createCategory.name$$"/> + <argument name="subCategoryName" value="$$createSubcategory.name$$"/> + </actionGroup> + </before> + <!-- Delete the Data after execution--> + <after> + <deleteData createDataKey="createCategory" stepKey="deleteProduct"/> + <deleteData createDataKey="simpleProductOne" stepKey="deleteCategory"/> + <magentoCLI command="config:set {{EnableInventoryCheckOnCartLoad.path}} {{EnableInventoryCheckOnCartLoad.value}}" stepKey="enableCartLoad"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + </after> + <!-- Open New tab--> + <openNewTab stepKey="openNewTab"/> + <!-- Open Product From AdminPage--> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="openProductEditPageinNewTab"> + <argument name="productId" value="$simpleProductOne.id$"/> + </actionGroup> + <!-- Set Stock Status of Product to Out Of Stock--> + <actionGroup ref="AdminSetStockStatusActionGroup" stepKey="outOfStockStatus"> + <argument name="stockStatus" value="Out of Stock"/> + </actionGroup> + <!-- Save Product--> + <actionGroup ref="SaveProductFormActionGroup" stepKey="clicksaveProduct"/> + <!-- Switch to Previous tab and Check Error message Product that you are trying to add is not available --> + <switchToPreviousTab stepKey="switchToPreviousTab"/> + <!-- Mouse Hover Product On Category Page--> + <actionGroup ref="StorefrontHoverProductOnCategoryPageActionGroup" stepKey="hoverProduct"/> + <!-- Select Add to cart--> + <click selector="{{StorefrontCategoryMainSection.addToCartButtonProductInfoHover}}" stepKey="toCategory"/> + <waitForPageLoad stepKey="wait"/> + <!-- Assert the Error Message--> + <see selector="{{StorefrontProductPageSection.errorMsg}}" userInput="Product that you are trying to add is not available." stepKey="seeErrorMessage"/> + </test> + +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml index f3389072f177..fa2f45d83cc3 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml @@ -34,5 +34,7 @@ <element name="massActionsOption" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//span[contains(@class, 'action-menu-item') and .= '{{action}}']" parameterized="true"/> <element name="gridDataRow" type="input" selector=".data-row .data-grid-cell-content"/> <element name="pagesGridRowByTitle" type="input" selector="//tbody//tr//td//div[contains(., '{{var1}}')]" parameterized="true" timeout="30"/> + <element name="saveFormRow" type="button" selector="//td//button//span[contains(text(),'Save')]/.."/> + <element name="selectLayout" type="select" selector="//tr[@class='data-grid-editable-row _odd-row']//select[@name='page_layout']" /> </section> </sections> diff --git a/app/code/Magento/Directory/Test/Mftf/Test/CustomCurrencySymbolWithSpaceTest.xml b/app/code/Magento/Directory/Test/Mftf/Test/CustomCurrencySymbolWithSpaceTest.xml index 50fb0fe48ac4..62cf00e7735b 100644 --- a/app/code/Magento/Directory/Test/Mftf/Test/CustomCurrencySymbolWithSpaceTest.xml +++ b/app/code/Magento/Directory/Test/Mftf/Test/CustomCurrencySymbolWithSpaceTest.xml @@ -18,6 +18,9 @@ <testCaseId value="AC-6031" /> <useCaseId value="ACP2E-1012"/> <group value="currency"/> + <skip> + <issueId value="ACQE-4266"/> + </skip> </annotations> <before> <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml index 569487c47da1..727d3293851f 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml @@ -9,6 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminMediaGalleryFolderSection"> + <element name="folderNewModalHeader" type="block" selector="//h1[contains(text(), 'New Folder Name')]"/> <element name="folderDeleteModalHeader" type="block" selector="//h1[contains(text(), 'Are you sure you want to delete this folder?')]"/> <element name="folderNewCreateButton" type="button" selector="#create_folder"/> @@ -28,5 +29,7 @@ <element name="activeDeleteFolderButton" type="button" selector="//h1[@class='modal-title' and contains(text(),'Insert File')]/../..//button[@id='delete_folder']"/> <element name="folderDeleteMessageTitle" type="block" selector="//h1[@class='modal-title' and contains(text(),'Are you sure you want to delete this folder?')]"/> <element name="folderDeleteMessageContent" type="block" selector="//div[@class='modal-content']//div[contains(text(),'The following folder is going to be deleted: wysiwyg/{{arg}}')]" parameterized="true"/> + </section> </sections> + diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/UserDeletesFolderFromMediaGalleryTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/UserDeletesFolderFromMediaGalleryTest.xml index f1db298764ee..91478877cfe5 100755 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/UserDeletesFolderFromMediaGalleryTest.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/UserDeletesFolderFromMediaGalleryTest.xml @@ -89,3 +89,4 @@ <waitForPageLoad stepKey="waitForMediaGalleryPageLoadPostFinalFolderDelete"/> </test> </tests> + diff --git a/app/code/Magento/Search/Test/Mftf/Test/AutoCompleteSearchTermsAndPhrasesWhileUserIsTypingTest.xml b/app/code/Magento/Search/Test/Mftf/Test/AutoCompleteSearchTermsAndPhrasesWhileUserIsTypingTest.xml index f549b02d2820..090fc1d3cb50 100644 --- a/app/code/Magento/Search/Test/Mftf/Test/AutoCompleteSearchTermsAndPhrasesWhileUserIsTypingTest.xml +++ b/app/code/Magento/Search/Test/Mftf/Test/AutoCompleteSearchTermsAndPhrasesWhileUserIsTypingTest.xml @@ -8,6 +8,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AutoCompleteSearchTermsAndPhrasesWhileUserIsTypingTest"> + <annotations> <stories value="Search Terms"/> <title value="In this test-case we need to verify that previously used earlier search terms are auto-complete"/> @@ -67,5 +68,6 @@ <actionGroup ref="StorefrontAssertProductNameOnProductMainPageActionGroup" stepKey="seeProductNameSku"> <argument name="productName" value="$$simpleProduct.name$$"/> </actionGroup> + </test> </tests> diff --git a/app/code/Magento/Shipping/Test/Mftf/Test/AdminDisableEnableShipmentCommentsAndVerifyNotifyCustomerByEmailCheckboxTest.xml b/app/code/Magento/Shipping/Test/Mftf/Test/AdminDisableEnableShipmentCommentsAndVerifyNotifyCustomerByEmailCheckboxTest.xml new file mode 100644 index 000000000000..f99a4808ba8c --- /dev/null +++ b/app/code/Magento/Shipping/Test/Mftf/Test/AdminDisableEnableShipmentCommentsAndVerifyNotifyCustomerByEmailCheckboxTest.xml @@ -0,0 +1,78 @@ +<?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="AdminDisableEnableShipmentCommentsAndVerifyNotifyCustomerByEmailCheckboxTest"> + <annotations> + <stories value="There is no Notify Customer by Email checkbox available when shipment comments are disabled"/> + <title value="Disable shipment comments section and validate Notify Customer by Email is disabled"/> + <description value="Disable shipment comments section and validate Notify Customer by Email is disabled"/> + <severity value="MAJOR"/> + <testCaseId value="AC-5678"/> + <group value="shipping"/> + </annotations> + <before> + <magentoCLI command="config:set {{EnableFlatRateConfigData.path}} {{EnableFlatRateConfigData.value}}" stepKey="enableFlatRate"/> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + + <!--create order for created product and create shipment also--> + <createData entity="CustomerCart" stepKey="createCustomerCart"> + <requiredEntity createDataKey="createCustomer"/> + </createData> + <createData entity="CustomerCartItem" stepKey="addCartItem"> + <requiredEntity createDataKey="createCustomerCart"/> + <requiredEntity createDataKey="createSimpleProduct"/> + </createData> + <createData entity="CustomerAddressInformation" stepKey="addCustomerOrderAddress"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> + <updateData createDataKey="createCustomerCart" entity="CustomerOrderPaymentMethod" stepKey="sendCustomerPaymentInformation"> + <requiredEntity createDataKey="createCustomerCart"/> + </updateData> + <createData entity="Shipment" stepKey="shipOrder"> + <requiredEntity createDataKey="createCustomerCart"/> + </createData> + <actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/> + + <!-- disable Shipment comments--> + <magentoCLI command="config:set sales_email/shipment_comment/enabled 0" stepKey="disableShipmentComments"/> + </before> + <after> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + </after> + + <!--open created order and then open shipment for that order--> + <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="openOrdersGrid"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFilters"/> + <grabTextFrom selector="{{AdminOrdersGridSection.orderIdByIncrementId($createCustomerCart.return$)}}" stepKey="orderId"/> + <actionGroup ref="FilterShipmentGridByOrderIdActionGroup" stepKey="filterForNewlyCreatedShipment"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <actionGroup ref="AdminSelectFirstGridRowActionGroup" stepKey="selectShipmentFromGrid"/> + + <!-- verify "Notify Customer by Email" checkbox should not be displayed.--> + <actionGroup ref="AssertAdminThereIsNoNotifyCustomerByEmailCheckboxActionGroup" stepKey="doNotSeeNotifyCustomerCheckbox"/> + + <!-- enable Shipment comments--> + <magentoCLI command="config:set sales_email/shipment_comment/enabled 1" stepKey="enableShipmentComments"/> + <actionGroup ref="AdminOrdersPageOpenActionGroup" stepKey="openOrdersGridSecondTime"/> + <actionGroup ref="AdminOrdersGridClearFiltersActionGroup" stepKey="clearFiltersSecondTime"/> + <actionGroup ref="FilterShipmentGridByOrderIdActionGroup" stepKey="filterForNewlyCreatedShipmentSecondTime"> + <argument name="orderId" value="$orderId"/> + </actionGroup> + <actionGroup ref="AdminSelectFirstGridRowActionGroup" stepKey="selectShipmentFromGridSecondTime"/> + + <!-- verify "Notify Customer by Email" checkbox should be displayed.--> + <seeElement selector="{{AdminShipmentMainActionsSection.notifyCustomerByEmail}}" stepKey="seeCheckbox"/> + </test> +</tests> + diff --git a/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php b/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php index 967826be09ce..94023d129d1d 100644 --- a/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/DataObjectProcessor.php @@ -46,6 +46,11 @@ class DataObjectProcessor */ private $processors; + /** + * @var array[] + */ + private $excludedMethodsClassMap; + /** * @param MethodsMap $methodsMapProcessor * @param TypeCaster $typeCaster @@ -53,6 +58,7 @@ class DataObjectProcessor * @param CustomAttributesProcessor $customAttributesProcessor * @param ExtensionAttributesProcessor $extensionAttributesProcessor * @param array $processors + * @param array $excludedMethodsClassMap */ public function __construct( MethodsMap $methodsMapProcessor, @@ -60,7 +66,8 @@ public function __construct( FieldNamer $fieldNamer, CustomAttributesProcessor $customAttributesProcessor, ExtensionAttributesProcessor $extensionAttributesProcessor, - array $processors = [] + array $processors = [], + array $excludedMethodsClassMap = [] ) { $this->methodsMapProcessor = $methodsMapProcessor; $this->typeCaster = $typeCaster; @@ -68,6 +75,7 @@ public function __construct( $this->extensionAttributesProcessor = $extensionAttributesProcessor; $this->customAttributesProcessor = $customAttributesProcessor; $this->processors = $processors; + $this->excludedMethodsClassMap = $excludedMethodsClassMap; } /** @@ -84,7 +92,13 @@ public function buildOutputDataArray($dataObject, $dataObjectType) $methods = $this->methodsMapProcessor->getMethodsMap($dataObjectType); $outputData = []; + $excludedMethodsForDataObjectType = $this->excludedMethodsClassMap[$dataObjectType] ?? []; + foreach (array_keys($methods) as $methodName) { + if (in_array($methodName, $excludedMethodsForDataObjectType)) { + continue; + } + if (!$this->methodsMapProcessor->isMethodValidForDataField($dataObjectType, $methodName)) { continue; } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/DataObjectProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/DataObjectProcessorTest.php index 8e55d4395d20..620b3684b4ab 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/DataObjectProcessorTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/DataObjectProcessorTest.php @@ -26,6 +26,11 @@ class DataObjectProcessorTest extends TestCase */ private $dataObjectProcessor; + /** + * @var MethodsMap + */ + private $methodsMapProcessor; + /** * @var ExtensionAttributesProcessor|MockObject */ @@ -34,7 +39,7 @@ class DataObjectProcessorTest extends TestCase protected function setUp(): void { $objectManager = new ObjectManager($this); - $methodsMapProcessor = $objectManager->getObject( + $this->methodsMapProcessor = $objectManager->getObject( MethodsMap::class, [ 'fieldNamer' => $objectManager->getObject(FieldNamer::class), @@ -48,7 +53,7 @@ protected function setUp(): void ->willReturn(['unserializedData']); $objectManager->setBackwardCompatibleProperty( - $methodsMapProcessor, + $this->methodsMapProcessor, 'serializer', $serializerMock ); @@ -56,27 +61,32 @@ protected function setUp(): void $this->extensionAttributesProcessorMock = $this->getMockBuilder(ExtensionAttributesProcessor::class) ->disableOriginalConstructor() ->getMock(); + } + + /** + * @param array $extensionAttributes + * @param array $excludedMethodsClassMap + * @param array $expectedOutput + * @dataProvider buildOutputDataArrayDataProvider + */ + public function testBuildOutputDataArray( + array $extensionAttributes, + array $excludedMethodsClassMap, + array $expectedOutput + ) { + $objectManager = new ObjectManager($this); $this->dataObjectProcessor = $objectManager->getObject( DataObjectProcessor::class, [ - 'methodsMapProcessor' => $methodsMapProcessor, + 'methodsMapProcessor' => $this->methodsMapProcessor, 'typeCaster' => $objectManager->getObject(TypeCaster::class), 'fieldNamer' => $objectManager->getObject(FieldNamer::class), - 'extensionAttributesProcessor' => $this->extensionAttributesProcessorMock + 'extensionAttributesProcessor' => $this->extensionAttributesProcessorMock, + 'excludedMethodsClassMap' => $excludedMethodsClassMap, ] ); - } - /** - * @param array $extensionAttributes - * @param array $expectedOutputDataArray - * - * @dataProvider buildOutputDataArrayDataProvider - */ - public function testBuildOutputDataArray($extensionAttributes, $expectedOutputDataArray) - { - $objectManager = new ObjectManager($this); /** @var TestDataObject $testDataObject */ $testDataObject = $objectManager->getObject( TestDataObject::class, @@ -87,13 +97,19 @@ public function testBuildOutputDataArray($extensionAttributes, $expectedOutputDa ] ); - $this->extensionAttributesProcessorMock->expects($this->once()) + if (in_array('getExtensionAttributes', $excludedMethodsClassMap[TestDataInterface::class] ?? [])) { + $expectedTimes = $this->never(); + } else { + $expectedTimes = $this->once(); + } + + $this->extensionAttributesProcessorMock->expects($expectedTimes) ->method('buildOutputDataArray') ->willReturn($extensionAttributes); $outputData = $this->dataObjectProcessor ->buildOutputDataArray($testDataObject, TestDataInterface::class); - $this->assertEquals($expectedOutputDataArray, $outputData); + $this->assertEquals($expectedOutput, $outputData); } /** @@ -101,26 +117,50 @@ public function testBuildOutputDataArray($extensionAttributes, $expectedOutputDa */ public function buildOutputDataArrayDataProvider() { - $expectedOutputDataArray = [ + $expectedOutput = [ 'id' => '1', 'address' => 'someAddress', 'default_shipping' => 'true', 'required_billing' => 'false', ]; - $extensionAttributeArray = [ + + $extensionAttributes = [ 'attribute1' => 'value1', - 'attribute2' => 'value2' + 'attribute2' => 'value2', ]; return [ - 'No Attributes' => [[], $expectedOutputDataArray], - 'With Attributes' => [ - $extensionAttributeArray, + 'No Extension Attributes or Excluded Methods' => [ + [], + [], + $expectedOutput, + ], + 'With Extension Attributes' => [ + $extensionAttributes, + [], array_merge( - $expectedOutputDataArray, - ['extension_attributes' => $extensionAttributeArray] - ) - ] + $expectedOutput, + ['extension_attributes' => $extensionAttributes] + ), + ], + 'With Excluded Method' => [ + [], + [ + TestDataInterface::class => [ + 'getAddress', + ], + ], + array_diff_key($expectedOutput, array_flip(['address'])), + ], + 'With getExtensionAttributes as Excluded Method' => [ + $extensionAttributes, + [ + TestDataInterface::class => [ + 'getExtensionAttributes', + ], + ], + $expectedOutput, + ], ]; } }