From 1c1e70e1f96e9e027b667a9c9fc4cb7aca78dc19 Mon Sep 17 00:00:00 2001 From: Sudheer S Date: Thu, 8 Oct 2020 16:50:34 +0530 Subject: [PATCH 01/59] 30349: Product filter with category_id does not work as expected - fixed total_count and items issues --- .../Model/Resolver/Products/DataProvider/ProductSearch.php | 2 +- .../CollectionProcessor/FilterProcessor/CategoryFilter.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php index 4807cad54bd50..13bd29e83d87f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/ProductSearch.php @@ -113,7 +113,7 @@ public function getList( $searchResults = $this->searchResultsFactory->create(); $searchResults->setSearchCriteria($searchCriteriaForCollection); $searchResults->setItems($collection->getItems()); - $searchResults->setTotalCount($searchResult->getTotalCount()); + $searchResults->setTotalCount($collection->getSize()); return $searchResults; } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php index f709f8cd6eb72..92888a2775e17 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php @@ -61,7 +61,6 @@ public function apply(Filter $filter, AbstractDb $collection) $category = $this->categoryFactory->create(); $this->categoryResourceModel->load($category, $categoryId); $categoryProducts[$categoryId] = $category->getProductCollection()->getAllIds(); - $collection->addCategoryFilter($category); } $categoryProductIds = array_unique(array_merge(...$categoryProducts)); From 2070e582f54d43e09f2b1471666d0fd746995bbd Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Mon, 12 Oct 2020 09:53:20 -0500 Subject: [PATCH 02/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Model/Indexer/Product/Price/AbstractAction.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php index f3a4b322e29df..b8896dd128f6b 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php @@ -387,12 +387,9 @@ protected function _reindexRows($changedIds = []) $parentProductsTypes = $this->getParentProductsTypes($changedIds); $changedIds = array_unique(array_merge($changedIds, ...array_values($parentProductsTypes))); + $pendingDeleteIds = $changedIds; $productsTypes = array_merge_recursive($productsTypes, $parentProductsTypes); - if ($changedIds) { - $this->deleteIndexData($changedIds); - } - $typeIndexers = $this->getTypeIndexers(); foreach ($typeIndexers as $productType => $indexer) { $entityIds = $productsTypes[$productType] ?? []; @@ -419,6 +416,11 @@ protected function _reindexRows($changedIds = []) $indexer->reindexEntity($entityIds); $this->_syncData($entityIds); } + $pendingDeleteIds = array_diff($pendingDeleteIds, $entityIds); + } + + if (!empty($pendingDeleteIds)) { + $this->deleteIndexData($pendingDeleteIds); } return $changedIds; From f19ea1f4b11cec03a19a4c4c4bff379aaa2c4a01 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Mon, 12 Oct 2020 13:59:31 -0500 Subject: [PATCH 03/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php index 578e3099a2fde..6d7e7293f9e9d 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php @@ -778,7 +778,7 @@ protected function _movePriceDataToIndexTable($entityIds = null) $select->where('entity_id in (?)', count($entityIds) > 0 ? $entityIds : 0, \Zend_Db::INT_TYPE); } - $query = $select->insertFromSelect($this->getIdxTable(), [], false); + $query = $select->insertFromSelect($this->getIdxTable(), [], true); $connection->query($query); $connection->delete($table); From 38715a87322c5066b2654ae7ddf69b61defa6450 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Mon, 12 Oct 2020 16:23:49 -0500 Subject: [PATCH 04/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Indexer/Product/Price/AbstractAction.php | 12 +-- .../Indexer/Product/Price/Action/Rows.php | 96 ++++++++++++++++++- 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php index b8896dd128f6b..fdbfad201954c 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php @@ -387,9 +387,12 @@ protected function _reindexRows($changedIds = []) $parentProductsTypes = $this->getParentProductsTypes($changedIds); $changedIds = array_unique(array_merge($changedIds, ...array_values($parentProductsTypes))); - $pendingDeleteIds = $changedIds; $productsTypes = array_merge_recursive($productsTypes, $parentProductsTypes); + if (!empty($changedIds)) { + $this->deleteIndexData($changedIds); + } + $typeIndexers = $this->getTypeIndexers(); foreach ($typeIndexers as $productType => $indexer) { $entityIds = $productsTypes[$productType] ?? []; @@ -416,11 +419,6 @@ protected function _reindexRows($changedIds = []) $indexer->reindexEntity($entityIds); $this->_syncData($entityIds); } - $pendingDeleteIds = array_diff($pendingDeleteIds, $entityIds); - } - - if (!empty($pendingDeleteIds)) { - $this->deleteIndexData($pendingDeleteIds); } return $changedIds; @@ -472,9 +470,7 @@ protected function _copyRelationIndexData($parentIds, $excludeIds = null) if (!empty($excludeIds)) { $select->where('child_id NOT IN(?)', $excludeIds); } - $children = $this->getConnection()->fetchCol($select); - if ($children) { foreach ($this->dimensionCollectionFactory->create() as $dimensions) { $select = $this->getConnection()->select()->from( diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php index 27b50eea883b0..ce2f1ff75adbe 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php @@ -5,12 +5,82 @@ */ namespace Magento\Catalog\Model\Indexer\Product\Price\Action; +use Magento\Directory\Model\CurrencyFactory; +use Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory; +use Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice; +use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\Factory; +use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\TierPrice; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Stdlib\DateTime; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Store\Model\StoreManagerInterface; + /** * Class Rows reindex action for mass actions * */ class Rows extends \Magento\Catalog\Model\Indexer\Product\Price\AbstractAction { + /** + * Default batch size + */ + private const BATCH_SIZE = 100; + + /** + * @var int + */ + private $batchSize; + + /** + * @param ScopeConfigInterface $config + * @param StoreManagerInterface $storeManager + * @param CurrencyFactory $currencyFactory + * @param TimezoneInterface $localeDate + * @param DateTime $dateTime + * @param Type $catalogProductType + * @param Factory $indexerPriceFactory + * @param DefaultPrice $defaultIndexerResource + * @param TierPrice|null $tierPriceIndexResource + * @param DimensionCollectionFactory|null $dimensionCollectionFactory + * @param TableMaintainer|null $tableMaintainer + * @param int|null $batchSize + * @SuppressWarnings(PHPMD.NPathComplexity) Added to backward compatibility with abstract class + * @SuppressWarnings(PHPMD.CyclomaticComplexity) Added to backward compatibility with abstract class + * @SuppressWarnings(PHPMD.ExcessiveParameterList) Added to backward compatibility with abstract class + */ + public function __construct( + ScopeConfigInterface $config, + StoreManagerInterface $storeManager, + CurrencyFactory $currencyFactory, + TimezoneInterface $localeDate, + DateTime $dateTime, + Type $catalogProductType, + Factory $indexerPriceFactory, + DefaultPrice $defaultIndexerResource, + TierPrice $tierPriceIndexResource = null, + DimensionCollectionFactory $dimensionCollectionFactory = null, + TableMaintainer $tableMaintainer = null, + ?int $batchSize = null + ) { + parent::__construct( + $config, + $storeManager, + $currencyFactory, + $localeDate, + $dateTime, + $catalogProductType, + $indexerPriceFactory, + $defaultIndexerResource, + $tierPriceIndexResource, + $dimensionCollectionFactory, + $tableMaintainer + ); + $this->batchSize = $batchSize ?? self::BATCH_SIZE; + } + /** * Execute Rows reindex * @@ -24,10 +94,28 @@ public function execute($ids) if (empty($ids)) { throw new \Magento\Framework\Exception\InputException(__('Bad value was supplied.')); } - try { - $this->_reindexRows($ids); - } catch (\Exception $e) { - throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()), $e); + $currentBatch = []; + $i = 0; + + foreach ($ids as $id) { + $currentBatch[] = $id; + if (++$i === $this->batchSize) { + try { + $this->_reindexRows($currentBatch); + } catch (\Exception $e) { + throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()), $e); + } + $i = 0; + $currentBatch = []; + } + } + + if (!empty($currentBatch)) { + try { + $this->_reindexRows($currentBatch); + } catch (\Exception $e) { + throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()), $e); + } } } } From 1c829a7233944b7ef7b05e53478f471cccb10c0f Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Mon, 12 Oct 2020 16:29:08 -0500 Subject: [PATCH 05/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Catalog/Model/Indexer/Product/Price/AbstractAction.php | 4 +++- .../ResourceModel/Product/Indexer/Price/DefaultPrice.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php index fdbfad201954c..f3a4b322e29df 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php @@ -389,7 +389,7 @@ protected function _reindexRows($changedIds = []) $changedIds = array_unique(array_merge($changedIds, ...array_values($parentProductsTypes))); $productsTypes = array_merge_recursive($productsTypes, $parentProductsTypes); - if (!empty($changedIds)) { + if ($changedIds) { $this->deleteIndexData($changedIds); } @@ -470,7 +470,9 @@ protected function _copyRelationIndexData($parentIds, $excludeIds = null) if (!empty($excludeIds)) { $select->where('child_id NOT IN(?)', $excludeIds); } + $children = $this->getConnection()->fetchCol($select); + if ($children) { foreach ($this->dimensionCollectionFactory->create() as $dimensions) { $select = $this->getConnection()->select()->from( diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php index 6d7e7293f9e9d..578e3099a2fde 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/DefaultPrice.php @@ -778,7 +778,7 @@ protected function _movePriceDataToIndexTable($entityIds = null) $select->where('entity_id in (?)', count($entityIds) > 0 ? $entityIds : 0, \Zend_Db::INT_TYPE); } - $query = $select->insertFromSelect($this->getIdxTable(), [], true); + $query = $select->insertFromSelect($this->getIdxTable(), [], false); $connection->query($query); $connection->delete($table); From ab42ff6465bf58a53b83810278b37085ff4e93aa Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Tue, 13 Oct 2020 16:15:04 -0500 Subject: [PATCH 06/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Indexer/Product/Price/Action/Rows.php | 1 - .../Indexer/Product/Price/Action/RowsTest.php | 161 +++++++++++++++++- 2 files changed, 156 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php index ce2f1ff75adbe..dfeb5b6bfea26 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php @@ -13,7 +13,6 @@ use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\Factory; use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\TierPrice; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Stdlib\DateTime; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Store\Model\StoreManagerInterface; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php index 4242ab7b2e914..9fd86e81c7a51 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php @@ -7,27 +7,178 @@ namespace Magento\Catalog\Test\Unit\Model\Indexer\Product\Price\Action; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Directory\Model\CurrencyFactory; +use Magento\Catalog\Model\Product\Type; +use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\Factory; +use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice; +use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\TierPrice; +use Magento\Catalog\Model\Indexer\Product\Price\DimensionCollectionFactory; +use Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer; use Magento\Catalog\Model\Indexer\Product\Price\Action\Rows; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Stdlib\DateTime; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Select; +use Magento\Framework\Indexer\MultiDimensionProvider; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; class RowsTest extends TestCase { /** * @var Rows */ - protected $_model; + private $actionRows; + + /** + * @var ScopeConfigInterface|MockObject + */ + private $config; + + /** + * @var StoreManagerInterface|MockObject + */ + private $storeManager; + + /** + * @var CurrencyFactory|MockObject + */ + private $currencyFactory; + + /** + * @var TimezoneInterface|MockObject + */ + private $localeDate; + + /** + * @var DateTime|MockObject + */ + private $dateTime; + + /** + * @var Type|MockObject + */ + private $catalogProductType; + + /** + * @var Factory|MockObject + */ + private $indexerPriceFactory; + + /** + * @var DefaultPrice|MockObject + */ + private $defaultIndexerResource; + + /** + * @var TierPrice|MockObject + */ + private $tierPriceIndexResource; + + /** + * @var DimensionCollectionFactory|MockObject + */ + private $dimensionCollectionFactory; + + /** + * @var TableMaintainer|MockObject + */ + private $tableMaintainer; protected function setUp(): void { - $objectManager = new ObjectManager($this); - $this->_model = $objectManager->getObject(Rows::class); + $this->config = $this->getMockBuilder(ScopeConfigInterface::class) + ->getMockForAbstractClass(); + $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class) + ->getMockForAbstractClass(); + $this->currencyFactory = $this->getMockBuilder(CurrencyFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->localeDate = $this->getMockBuilder(TimezoneInterface::class) + ->getMockForAbstractClass(); + $this->dateTime = $this->getMockBuilder(DateTime::class) + ->disableOriginalConstructor() + ->getMock(); + $this->catalogProductType = $this->getMockBuilder(Type::class) + ->disableOriginalConstructor() + ->getMock(); + $this->indexerPriceFactory = $this->getMockBuilder(Factory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->defaultIndexerResource = $this->getMockBuilder(DefaultPrice::class) + ->disableOriginalConstructor() + ->getMock(); + $this->tierPriceIndexResource = $this->getMockBuilder(TierPrice::class) + ->disableOriginalConstructor() + ->getMock(); + $this->dimensionCollectionFactory = $this->getMockBuilder(DimensionCollectionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->tableMaintainer = $this->getMockBuilder(TableMaintainer::class) + ->disableOriginalConstructor() + ->getMock(); + $batchSize = 2; + + $this->actionRows = new Rows( + $this->config, + $this->storeManager, + $this->currencyFactory, + $this->localeDate, + $this->dateTime, + $this->catalogProductType, + $this->indexerPriceFactory, + $this->defaultIndexerResource, + $this->tierPriceIndexResource, + $this->dimensionCollectionFactory, + $this->tableMaintainer, + $batchSize + ); } public function testEmptyIds() { $this->expectException('Magento\Framework\Exception\InputException'); $this->expectExceptionMessage('Bad value was supplied.'); - $this->_model->execute(null); + $this->actionRows->execute(null); + } + + public function testBatchProcessing() + { + $ids = [1, 2, 3, 4]; + $select = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + $select->expects($this->any())->method('from')->willReturnSelf(); + $select->expects($this->any())->method('where')->willReturnSelf(); + $select->expects($this->any())->method('join')->willReturnSelf(); + $adapter = $this->getMockBuilder(AdapterInterface::class)->getMockForAbstractClass(); + $adapter->expects($this->any())->method('select')->willReturn($select); + $this->defaultIndexerResource->expects($this->any()) + ->method('getConnection') + ->willReturn($adapter); + $adapter->expects($this->any()) + ->method('fetchAll') + ->with($select) + ->willReturn([]); + $adapter->expects($this->any()) + ->method('fetchPairs') + ->with($select) + ->willReturn([]); + $multiDimensionProvider = $this->getMockBuilder(MultiDimensionProvider::class) + ->disableOriginalConstructor() + ->getMock(); + $this->dimensionCollectionFactory->expects($this->exactly(2)) + ->method('create') + ->willReturn($multiDimensionProvider); + $iterator = new \ArrayObject([]); + $multiDimensionProvider->expects($this->exactly(2)) + ->method('getIterator') + ->willReturn($iterator); + $this->catalogProductType->expects($this->any()) + ->method('getTypesByPriority') + ->willReturn([]); + $this->actionRows->execute($ids); } } From 90372d9caa114b021447b0da1d793756617f9f1f Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Tue, 13 Oct 2020 19:16:30 -0500 Subject: [PATCH 07/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php index dfeb5b6bfea26..acbe20721ee9e 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Rows.php @@ -20,6 +20,7 @@ /** * Class Rows reindex action for mass actions * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) to preserve compatibility with parent class */ class Rows extends \Magento\Catalog\Model\Indexer\Product\Price\AbstractAction { From dd159ef462103a5b923a5115f5dfccd3e179a0e4 Mon Sep 17 00:00:00 2001 From: Sudheer S Date: Wed, 14 Oct 2020 16:11:14 +0530 Subject: [PATCH 08/59] 30349: Product filter with category_id does not work as expected - fixed query returns missing items --- .../CollectionProcessor/FilterProcessor/CategoryFilter.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php index 92888a2775e17..7fd4b4bfa8e35 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php @@ -51,6 +51,11 @@ public function __construct( */ public function apply(Filter $filter, AbstractDb $collection) { + $conditionType = $filter->getConditionType(); + if ($conditionType !== 'eq') { + return true; + } + $categoryIds = $filter->getValue(); if (!is_array($categoryIds)) { $categoryIds = [$categoryIds]; @@ -61,6 +66,7 @@ public function apply(Filter $filter, AbstractDb $collection) $category = $this->categoryFactory->create(); $this->categoryResourceModel->load($category, $categoryId); $categoryProducts[$categoryId] = $category->getProductCollection()->getAllIds(); + $collection->addCategoryFilter($category); } $categoryProductIds = array_unique(array_merge(...$categoryProducts)); From f4b7937cba82d62caf780f18bd7e51e93738ecf5 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Wed, 14 Oct 2020 10:05:08 -0500 Subject: [PATCH 09/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Model/Indexer/Product/Price/Action/RowsTest.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php index 9fd86e81c7a51..44ac8b67d392b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php @@ -25,6 +25,11 @@ use PHPUnit\Framework\TestCase; use PHPUnit\Framework\MockObject\MockObject; +/** + * Test coverage for the rows action + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) to preserve compatibility with parent class + */ class RowsTest extends TestCase { /** @@ -172,13 +177,16 @@ public function testBatchProcessing() $this->dimensionCollectionFactory->expects($this->exactly(2)) ->method('create') ->willReturn($multiDimensionProvider); - $iterator = new \ArrayObject([]); + $iterator = new \ArrayIterator([]); $multiDimensionProvider->expects($this->exactly(2)) ->method('getIterator') ->willReturn($iterator); $this->catalogProductType->expects($this->any()) ->method('getTypesByPriority') ->willReturn([]); + $adapter->expects($this->any()) + ->method('getPrimaryKeyName') + ->willReturn(['COLUMNS_LIST'=>['entity_id']]); $this->actionRows->execute($ids); } } From 22692c74455f87e4a987e10d8686c7cd49f0426d Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Wed, 14 Oct 2020 12:19:42 -0500 Subject: [PATCH 10/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Unit/Model/Indexer/Product/Price/Action/RowsTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php index 44ac8b67d392b..e6ef516ac0663 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php @@ -184,9 +184,12 @@ public function testBatchProcessing() $this->catalogProductType->expects($this->any()) ->method('getTypesByPriority') ->willReturn([]); - $adapter->expects($this->any()) + $adapter->expects($this->once()) + ->method('getIndexList') + ->willReturn(['entity_id'=>['COLUMNS_LIST'=>['test']]]); + $adapter->expects($this->once()) ->method('getPrimaryKeyName') - ->willReturn(['COLUMNS_LIST'=>['entity_id']]); + ->willReturn('entity_id'); $this->actionRows->execute($ids); } } From a1bf66a893c244293840a17365cdee3fac2b6fc9 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov Date: Wed, 14 Oct 2020 13:33:54 -0500 Subject: [PATCH 11/59] MC-38038: Partial reindex of prices causes empty categories (missed products) --- .../Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php index e6ef516ac0663..816dc923ebc0a 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Price/Action/RowsTest.php @@ -184,10 +184,10 @@ public function testBatchProcessing() $this->catalogProductType->expects($this->any()) ->method('getTypesByPriority') ->willReturn([]); - $adapter->expects($this->once()) + $adapter->expects($this->exactly(2)) ->method('getIndexList') ->willReturn(['entity_id'=>['COLUMNS_LIST'=>['test']]]); - $adapter->expects($this->once()) + $adapter->expects($this->exactly(2)) ->method('getPrimaryKeyName') ->willReturn('entity_id'); $this->actionRows->execute($ids); From a56f2c5ea7fa7c67644b079d4048c737edabaacf Mon Sep 17 00:00:00 2001 From: Arnob Saha Date: Mon, 21 Sep 2020 01:33:14 -0500 Subject: [PATCH 12/59] MC-36954: [Magento Cloud] Coupon Code with single payment option - Adding key check with the PO --- .../OfflinePayments/Model/Purchaseorder.php | 5 +-- .../Plugin/ValidatePurchaseOrderNumber.php | 43 ++++++++++++++++++ .../Test/Unit/Model/PurchaseorderTest.php | 6 +-- .../Magento/OfflinePayments/composer.json | 3 +- app/code/Magento/OfflinePayments/etc/di.xml | 3 ++ ...etPurchaseOrderPaymentMethodOnCartTest.php | 17 ++++--- ...etPurchaseOrderPaymentMethodOnCartTest.php | 17 ++++--- .../Quote/Model/QuoteManagementTest.php | 44 +++++++++++++++++++ .../_files/quote_with_purchase_order.php | 43 ++++++++++++++++++ .../quote_with_purchase_order_rollback.php | 21 +++++++++ 10 files changed, 183 insertions(+), 19 deletions(-) create mode 100644 app/code/Magento/OfflinePayments/Plugin/ValidatePurchaseOrderNumber.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order.php create mode 100644 dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order_rollback.php diff --git a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php index fe30570aba50d..21790f3ac20bb 100644 --- a/app/code/Magento/OfflinePayments/Model/Purchaseorder.php +++ b/app/code/Magento/OfflinePayments/Model/Purchaseorder.php @@ -10,6 +10,7 @@ /** * Class Purchaseorder * + * Update additional payments fields and validate the payment data * @method \Magento\Quote\Api\Data\PaymentMethodExtensionInterface getExtensionAttributes() * * @api @@ -68,10 +69,6 @@ public function validate() { parent::validate(); - if (empty($this->getInfoInstance()->getPoNumber())) { - throw new LocalizedException(__('Purchase order number is a required field.')); - } - return $this; } } diff --git a/app/code/Magento/OfflinePayments/Plugin/ValidatePurchaseOrderNumber.php b/app/code/Magento/OfflinePayments/Plugin/ValidatePurchaseOrderNumber.php new file mode 100644 index 0000000000000..18e80864f434b --- /dev/null +++ b/app/code/Magento/OfflinePayments/Plugin/ValidatePurchaseOrderNumber.php @@ -0,0 +1,43 @@ +getPayment(); + if ($payment->getMethod() === Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE + && empty($payment->getPoNumber())) { + throw new LocalizedException(__('Purchase order number is a required field.')); + } + } +} diff --git a/app/code/Magento/OfflinePayments/Test/Unit/Model/PurchaseorderTest.php b/app/code/Magento/OfflinePayments/Test/Unit/Model/PurchaseorderTest.php index c4c717550dbae..2bbaad03d4b87 100644 --- a/app/code/Magento/OfflinePayments/Test/Unit/Model/PurchaseorderTest.php +++ b/app/code/Magento/OfflinePayments/Test/Unit/Model/PurchaseorderTest.php @@ -66,9 +66,6 @@ public function testAssignData() public function testValidate() { - $this->expectException(LocalizedException::class); - $this->expectExceptionMessage('Purchase order number is a required field.'); - $data = new DataObject([]); $addressMock = $this->getMockForAbstractClass(OrderAddressInterface::class); @@ -84,6 +81,7 @@ public function testValidate() $this->object->setData('info_instance', $instance); $this->object->assignData($data); - $this->object->validate(); + $result = $this->object->validate(); + $this->assertEquals($result, $this->object); } } diff --git a/app/code/Magento/OfflinePayments/composer.json b/app/code/Magento/OfflinePayments/composer.json index 56c7eb2778c48..237812a205130 100644 --- a/app/code/Magento/OfflinePayments/composer.json +++ b/app/code/Magento/OfflinePayments/composer.json @@ -8,7 +8,8 @@ "php": "~7.3.0||~7.4.0", "magento/framework": "*", "magento/module-checkout": "*", - "magento/module-payment": "*" + "magento/module-payment": "*", + "magento/module-quote": "*" }, "suggest": { "magento/module-config": "*" diff --git a/app/code/Magento/OfflinePayments/etc/di.xml b/app/code/Magento/OfflinePayments/etc/di.xml index 1e3d7cba3b86a..e0a2e250eadcd 100644 --- a/app/code/Magento/OfflinePayments/etc/di.xml +++ b/app/code/Magento/OfflinePayments/etc/di.xml @@ -13,4 +13,7 @@ + + + diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php index 1777289afe5bc..69dc78b9d08d9 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPurchaseOrderPaymentMethodOnCartTest.php @@ -7,7 +7,6 @@ namespace Magento\GraphQl\Quote\Customer; -use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\OfflinePayments\Model\Purchaseorder; @@ -100,9 +99,6 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() */ public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumber() { - $this->expectException(\Exception::class); - $this->expectExceptionMessage('Purchase order number is a required field.'); - $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); @@ -122,7 +118,18 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumbe } } QUERY; - $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + $response = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertEquals( + $methodCode, + $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code'] + ); + self::assertArrayNotHasKey( + 'purchase_order_number', + $response['setPaymentMethodOnCart']['cart']['selected_payment_method'] + ); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php index 2c93a27012a01..121b04cc8ed11 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetPurchaseOrderPaymentMethodOnCartTest.php @@ -7,7 +7,6 @@ namespace Magento\GraphQl\Quote\Guest; -use Exception; use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; use Magento\OfflinePayments\Model\Purchaseorder; use Magento\TestFramework\Helper\Bootstrap; @@ -91,9 +90,6 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithSimpleProduct() */ public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumber() { - $this->expectException(\Exception::class); - $this->expectExceptionMessage('Purchase order number is a required field.'); - $methodCode = Purchaseorder::PAYMENT_METHOD_PURCHASEORDER_CODE; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); @@ -113,7 +109,18 @@ public function testSetPurchaseOrderPaymentMethodOnCartWithoutPurchaseOrderNumbe } } QUERY; - $this->graphQlMutation($query); + $response = $this->graphQlMutation($query); + self::assertArrayHasKey('setPaymentMethodOnCart', $response); + self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); + self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); + self::assertEquals( + $methodCode, + $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code'] + ); + self::assertArrayNotHasKey( + 'purchase_order_number', + $response['setPaymentMethodOnCart']['cart']['selected_payment_method'] + ); } /** diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php index 26ae82120b2c7..c02d32430939a 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php @@ -13,6 +13,7 @@ use Magento\Customer\Model\Vat; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\DataObject; +use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\StateException; use Magento\Framework\ObjectManagerInterface; @@ -134,6 +135,49 @@ public function testSubmitGuestCustomer(): void self::assertEquals(3, $quoteAfterOrderPlaced->getCustomerTaxClassId()); } + /** + * Creates order with purchase_order payment method + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Sales/_files/quote_with_purchase_order.php + * + * @return void + * @throws CouldNotSaveException + */ + public function testSubmitWithPurchaseOrder(): void + { + $paymentMethodName = 'purchaseorder'; + $poNumber = '12345678'; + $quote = $this->getQuoteByReservedOrderId->execute('test_order_1'); + $quote->getPayment()->setPoNumber($poNumber); + $quote->collectTotals()->save(); + $orderId = $this->cartManagement->placeOrder($quote->getId()); + $order = $this->orderRepository->get($orderId); + $orderItems = $order->getItems(); + $this->assertCount(1, $orderItems); + $payment = $order->getPayment(); + $this->assertEquals($paymentMethodName, $payment->getMethod()); + $this->assertEquals($poNumber, $payment->getPoNumber()); + } + + /** + * Creates order with purchase_order payment method without po_number + * + * @magentoAppIsolation enabled + * @magentoDataFixture Magento/Sales/_files/quote_with_purchase_order.php + * + * @return void + * @throws CouldNotSaveException + */ + public function testSubmitWithPurchaseOrderWithException(): void + { + $this->expectException(LocalizedException::class); + $this->expectExceptionMessage('Purchase order number is a required field.'); + + $quote = $this->getQuoteByReservedOrderId->execute('test_order_1'); + $this->cartManagement->placeOrder($quote->getId()); + } + /** * Tries to create order with product that has child items and one of them was deleted. * diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order.php new file mode 100644 index 0000000000000..96a5484746da2 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order.php @@ -0,0 +1,43 @@ +requireDataFixture('Magento/Checkout/_files/quote_with_address.php'); +/** @var QuoteFactory $quoteFactory */ +$quoteFactory = Bootstrap::getObjectManager()->get(QuoteFactory::class); +/** @var QuoteResource $quoteResource */ +$quoteResource = Bootstrap::getObjectManager()->get(QuoteResource::class); +$quote = $quoteFactory->create(); +$quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); + +/** @var $rate Rate */ +$rate = Bootstrap::getObjectManager()->create( + Rate::class +); +$rate->setCode('freeshipping_freeshipping'); +$rate->getPrice(100); + +$quote->getShippingAddress()->setShippingMethod('freeshipping_freeshipping'); +$quote->getShippingAddress()->addShippingRate($rate); +$quote->getPayment()->setMethod('purchaseorder'); + +$quote->collectTotals(); +$quote->save(); +$quote->getPayment()->setMethod('purchaseorder'); + +$quoteIdMask = Bootstrap::getObjectManager() + ->create(QuoteIdMaskFactory::class) + ->create(); +$quoteIdMask->setQuoteId($quote->getId()); +$quoteIdMask->setDataChanges(true); +$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order_rollback.php new file mode 100644 index 0000000000000..84d5ef051519c --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_purchase_order_rollback.php @@ -0,0 +1,21 @@ +requireDataFixture('Magento/Sales/_files/default_rollback.php'); + +/** @var $objectManager \Magento\TestFramework\ObjectManager */ +$objectManager = Bootstrap::getObjectManager(); +$objectManager->get(Registry::class)->unregister('quote'); +$quote = $objectManager->create(Quote::class); +$quote->load('test_order_1', 'reserved_order_id')->delete(); From aa34315ab9c12729b6936905394d0f1280a115f9 Mon Sep 17 00:00:00 2001 From: Arnob Saha Date: Wed, 23 Sep 2020 15:07:44 -0500 Subject: [PATCH 13/59] MC-37794: [REST] Order has wrong number of items shipped via REST API - Reverting the changes of MC-35633 in scope of MC-37794 --- app/code/Magento/Sales/Model/ShipOrder.php | 38 +-- .../Plugin/ProcessOrderAndShipmentViaAPI.php | 241 -------------- .../Sales/Test/Unit/Model/ShipOrderTest.php | 2 +- app/code/Magento/Sales/etc/webapi_rest/di.xml | 3 - app/code/Magento/Sales/etc/webapi_soap/di.xml | 3 - .../Sales/Service/V1/ShipmentCreateTest.php | 307 +++--------------- .../order_with_bundle_shipped_separately.php | 4 - 7 files changed, 65 insertions(+), 533 deletions(-) delete mode 100644 app/code/Magento/Sales/Plugin/ProcessOrderAndShipmentViaAPI.php diff --git a/app/code/Magento/Sales/Model/ShipOrder.php b/app/code/Magento/Sales/Model/ShipOrder.php index f955f6574a7b2..3bb8527d6e516 100644 --- a/app/code/Magento/Sales/Model/ShipOrder.php +++ b/app/code/Magento/Sales/Model/ShipOrder.php @@ -5,25 +5,15 @@ */ namespace Magento\Sales\Model; -use DomainException; use Magento\Framework\App\ResourceConnection; -use Magento\Sales\Api\Data\ShipmentCommentCreationInterface; -use Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface; -use Magento\Sales\Api\Data\ShipmentItemCreationInterface; -use Magento\Sales\Api\Data\ShipmentPackageCreationInterface; -use Magento\Sales\Api\Data\ShipmentTrackCreationInterface; -use Magento\Sales\Api\Exception\CouldNotShipExceptionInterface; -use Magento\Sales\Api\Exception\DocumentValidationExceptionInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Api\ShipmentRepositoryInterface; use Magento\Sales\Api\ShipOrderInterface; -use Magento\Sales\Exception\CouldNotShipException; -use Magento\Sales\Exception\DocumentValidationException; use Magento\Sales\Model\Order\Config as OrderConfig; use Magento\Sales\Model\Order\OrderStateResolverInterface; +use Magento\Sales\Model\Order\ShipmentDocumentFactory; use Magento\Sales\Model\Order\Shipment\NotifierInterface; use Magento\Sales\Model\Order\Shipment\OrderRegistrarInterface; -use Magento\Sales\Model\Order\ShipmentDocumentFactory; use Magento\Sales\Model\Order\Validation\ShipOrderInterface as ShipOrderValidator; use Psr\Log\LoggerInterface; @@ -126,27 +116,29 @@ public function __construct( * Process the shipment and save shipment and order data * * @param int $orderId - * @param ShipmentItemCreationInterface[] $items + * @param \Magento\Sales\Api\Data\ShipmentItemCreationInterface[] $items * @param bool $notify * @param bool $appendComment - * @param ShipmentCommentCreationInterface|null $comment - * @param ShipmentTrackCreationInterface[] $tracks - * @param ShipmentPackageCreationInterface[] $packages - * @param ShipmentCreationArgumentsInterface|null $arguments + * @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment + * @param \Magento\Sales\Api\Data\ShipmentTrackCreationInterface[] $tracks + * @param \Magento\Sales\Api\Data\ShipmentPackageCreationInterface[] $packages + * @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface|null $arguments * @return int - * @throws DocumentValidationExceptionInterface - * @throws CouldNotShipExceptionInterface - * @throws DomainException + * @throws \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface + * @throws \Magento\Sales\Api\Exception\CouldNotShipExceptionInterface + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \DomainException */ public function execute( $orderId, array $items = [], $notify = false, $appendComment = false, - ShipmentCommentCreationInterface $comment = null, + \Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null, array $tracks = [], array $packages = [], - ShipmentCreationArgumentsInterface $arguments = null + \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null ) { $connection = $this->resourceConnection->getConnection('sales'); $order = $this->orderRepository->get($orderId); @@ -170,7 +162,7 @@ public function execute( $packages ); if ($validationMessages->hasMessages()) { - throw new DocumentValidationException( + throw new \Magento\Sales\Exception\DocumentValidationException( __("Shipment Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages())) ); } @@ -189,7 +181,7 @@ public function execute( } catch (\Exception $e) { $this->logger->critical($e); $connection->rollBack(); - throw new CouldNotShipException( + throw new \Magento\Sales\Exception\CouldNotShipException( __('Could not save a shipment, see error log for details') ); } diff --git a/app/code/Magento/Sales/Plugin/ProcessOrderAndShipmentViaAPI.php b/app/code/Magento/Sales/Plugin/ProcessOrderAndShipmentViaAPI.php deleted file mode 100644 index 2f81de65fad74..0000000000000 --- a/app/code/Magento/Sales/Plugin/ProcessOrderAndShipmentViaAPI.php +++ /dev/null @@ -1,241 +0,0 @@ -shipmentLoader = $shipmentLoader; - $this->transaction = $transaction; - } - - /** - * Process shipping details before saving shipment via API - * - * @param ShipmentRepository $shipmentRepository - * @param ShipmentInterface $shipmentData - * @return array - * @throws LocalizedException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function beforeSave( - ShipmentRepository $shipmentRepository, - ShipmentInterface $shipmentData - ): array { - $this->shipmentLoader->setOrderId($shipmentData->getOrderId()); - $trackData = !empty($shipmentData->getTracks()) ? - $this->getShipmentTracking($shipmentData) : []; - $this->shipmentLoader->setTracking($trackData); - $shipmentItems = !empty($shipmentData) ? - $this->getShipmentItems($shipmentData) : []; - $orderItems = []; - if (!empty($shipmentData)) { - $order = $shipmentData->getOrder(); - $orderItems = $order ? $this->getOrderItems($order) : []; - } - $data = (!empty($shipmentItems) && !empty($orderItems)) ? - $this->getShippingData($shipmentItems, $orderItems) : []; - $this->shipmentLoader->setShipment($data); - $shipment = $this->shipmentLoader->load(); - $shipment = empty($shipment) ? $shipmentData - : $this->processShippingDetails($shipmentData, $shipment); - return [$shipment]; - } - - /** - * Save order data after saving shipment via API - * - * @param ShipmentRepository $shipmentRepository - * @param ShipmentInterface $shipment - * @return ShipmentInterface - * @throws Exception - */ - public function afterSave( - ShipmentRepository $shipmentRepository, - ShipmentInterface $shipment - ): ShipmentInterface { - $shipmentDetails = $shipmentRepository->get($shipment->getEntityId()); - $order = $shipmentDetails->getOrder(); - $shipmentItems = !empty($shipment) ? - $this->getShipmentItems($shipment) : []; - $this->processOrderItems($order, $shipmentItems); - $order->setIsInProcess(true); - $this->transaction - ->addObject($order) - ->save(); - return $shipment; - } - - /** - * Process shipment items - * - * @param ShipmentInterface $shipment - * @return array - * @throws LocalizedException - */ - private function getShipmentItems(ShipmentInterface $shipment): array - { - $shipmentItems = []; - foreach ($shipment->getItems() as $item) { - $sku = $item->getSku(); - if (isset($sku)) { - $shipmentItems[$sku]['qty'] = $item->getQty(); - } - } - return $shipmentItems; - } - - /** - * Get shipment tracking data from the shipment array - * - * @param ShipmentInterface $shipment - * @return array - */ - private function getShipmentTracking(ShipmentInterface $shipment): array - { - $trackData = []; - foreach ($shipment->getTracks() as $key => $track) { - $trackData[$key]['number'] = $track->getTrackNumber(); - $trackData[$key]['title'] = $track->getTitle(); - $trackData[$key]['carrier_code'] = $track->getCarrierCode(); - } - return $trackData; - } - - /** - * Get orderItems from shipment order - * - * @param Order $order - * @return array - */ - private function getOrderItems(Order $order): array - { - $orderItems = []; - foreach ($order->getItems() as $item) { - $orderItems[$item->getSku()] = $item->getItemId(); - } - return $orderItems; - } - - /** - * Get available shipping data from shippingItems and orderItems - * - * @param array $shipmentItems - * @param array $orderItems - * @return array - * @throws LocalizedException - */ - private function getShippingData(array $shipmentItems, array $orderItems): array - { - $data = []; - foreach ($shipmentItems as $shippingItemSku => $shipmentItem) { - if (isset($orderItems[$shippingItemSku])) { - $itemId = (int) $orderItems[$shippingItemSku]; - $data['items'][$itemId] = $shipmentItem['qty']; - } - } - return $data; - } - - /** - * Process shipping comments if available - * - * @param ShipmentInterface $shipmentData - * @param ShipmentInterface $shipment - * @return void - */ - private function processShippingComments(ShipmentInterface $shipmentData, ShipmentInterface $shipment): void - { - foreach ($shipmentData->getComments() as $comment) { - $shipment->addComment( - $comment->getComment(), - $comment->getIsCustomerNotified(), - $comment->getIsVisibleOnFront() - ); - $shipment->setCustomerNote($comment->getComment()); - $shipment->setCustomerNoteNotify((bool) $comment->getIsCustomerNotified()); - } - } - - /** - * Process shipping details - * - * @param ShipmentInterface $shipmentData - * @param ShipmentInterface $shipment - * @return ShipmentInterface - */ - private function processShippingDetails( - ShipmentInterface $shipmentData, - ShipmentInterface $shipment - ): ShipmentInterface { - if (empty($shipment->getItems())) { - $shipment->setItems($shipmentData->getItems()); - } - if (!empty($shipmentData->getComments())) { - $this->processShippingComments($shipmentData, $shipment); - } - if ((int) $shipment->getTotalQty() < 1) { - $shipment->setTotalQty($shipmentData->getTotalQty()); - } - return $shipment; - } - - /** - * Process order items data and set the proper item qty - * - * @param Order $order - * @param array $shipmentItems - * @throws LocalizedException - */ - private function processOrderItems(Order $order, array $shipmentItems): void - { - /** @var Item $item */ - foreach ($order->getAllItems() as $item) { - if (isset($shipmentItems[$item->getSku()])) { - $qty = (float)$shipmentItems[$item->getSku()]['qty']; - $item->setQty($qty); - if ((float)$item->getQtyToShip() > 0) { - $item->setQtyShipped((float)$item->getQtyToShip()); - } - } - } - } -} diff --git a/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php index 77cd6a058df6f..a31b79fcb0c5c 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/ShipOrderTest.php @@ -189,7 +189,7 @@ protected function setUp(): void ->getMockForAbstractClass(); $this->shipOrderValidatorMock = $this->getMockBuilder(ShipOrderInterface::class) ->disableOriginalConstructor() - ->getMock(); + ->getMockForAbstractClass(); $this->validationMessagesMock = $this->getMockBuilder(ValidatorResultInterface::class) ->disableOriginalConstructor() ->setMethods(['hasMessages', 'getMessages', 'addMessage']) diff --git a/app/code/Magento/Sales/etc/webapi_rest/di.xml b/app/code/Magento/Sales/etc/webapi_rest/di.xml index 1a8478438b04a..5d7838297a7c7 100644 --- a/app/code/Magento/Sales/etc/webapi_rest/di.xml +++ b/app/code/Magento/Sales/etc/webapi_rest/di.xml @@ -19,7 +19,4 @@ - - - diff --git a/app/code/Magento/Sales/etc/webapi_soap/di.xml b/app/code/Magento/Sales/etc/webapi_soap/di.xml index 1a8478438b04a..5d7838297a7c7 100644 --- a/app/code/Magento/Sales/etc/webapi_soap/di.xml +++ b/app/code/Magento/Sales/etc/webapi_soap/di.xml @@ -19,7 +19,4 @@ - - - diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php index 29a11f9d68e8f..dab4ad05f84d3 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentCreateTest.php @@ -6,10 +6,6 @@ namespace Magento\Sales\Service\V1; -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\Webapi\Rest\Request; -use Magento\Sales\Model\Order; -use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\WebapiAbstract; /** @@ -26,78 +22,23 @@ class ShipmentCreateTest extends WebapiAbstract const SERVICE_VERSION = 'V1'; /** - * @var ObjectManagerInterface + * @var \Magento\Framework\ObjectManagerInterface */ protected $objectManager; protected function setUp(): void { - $this->objectManager = Bootstrap::getObjectManager(); + $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); } /** - * Test save shipment return valid result with multiple tracks with multiple comments - * * @magentoApiDataFixture Magento/Sales/_files/order.php */ - public function testInvokeWithMultipleTrackAndComments() + public function testInvoke() { - $data = $this->getEntityData(); - $result = $this->_webApiCall( - $this->getServiceInfo(), - [ - 'entity' => $data['shipment data with multiple tracking and multiple comments']] - ); - $this->assertNotEmpty($result); - $this->assertEquals(3, count($result['tracks'])); - $this->assertEquals(3, count($result['comments'])); - } - - /** - * Test save shipment return valid result with multiple tracks with no comments - * - * @magentoApiDataFixture Magento/Sales/_files/order.php - */ - public function testInvokeWithMultipleTrackAndNoComments() - { - $data = $this->getEntityData(); - $result = $this->_webApiCall( - $this->getServiceInfo(), - [ - 'entity' => $data['shipment data with multiple tracking']] - ); - $this->assertNotEmpty($result); - $this->assertEquals(3, count($result['tracks'])); - $this->assertEquals(0, count($result['comments'])); - } - - /** - * Test save shipment return valid result with no tracks with multiple comments - * - * @magentoApiDataFixture Magento/Sales/_files/order.php - */ - public function testInvokeWithNoTrackAndMultipleComments() - { - $data = $this->getEntityData(); - $result = $this->_webApiCall( - $this->getServiceInfo(), - [ - 'entity' => $data['shipment data with multiple comments']] - ); - $this->assertNotEmpty($result); - $this->assertEquals(0, count($result['tracks'])); - $this->assertEquals(3, count($result['comments'])); - } - - /** - * @return array - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function getEntityData() - { - $existingOrder = $this->getOrder('100000001'); - $orderItem = current($existingOrder->getAllItems()); - + /** @var \Magento\Sales\Model\Order $order */ + $order = $this->objectManager->create(\Magento\Sales\Model\Order::class)->loadByIncrementId('100000001'); + $orderItem = current($order->getAllItems()); $items = [ [ 'order_item_id' => $orderItem->getId(), @@ -114,201 +55,10 @@ public function getEntityData() 'weight' => null, ], ]; - return [ - 'shipment data with multiple tracking and multiple comments' => [ - 'order_id' => $existingOrder->getId(), - 'entity_id' => null, - 'store_id' => null, - 'total_weight' => null, - 'total_qty' => null, - 'email_sent' => null, - 'customer_id' => null, - 'shipping_address_id' => null, - 'billing_address_id' => null, - 'shipment_status' => null, - 'increment_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'shipping_label' => null, - 'tracks' => [ - [ - 'carrier_code' => 'UPS', - 'order_id' => $existingOrder->getId(), - 'title' => 'ground', - 'description' => null, - 'track_number' => '12345678', - 'parent_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'qty' => null, - 'weight' => null - ], - [ - 'carrier_code' => 'UPS', - 'order_id' => $existingOrder->getId(), - 'title' => 'ground', - 'description' => null, - 'track_number' => '654563221', - 'parent_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'qty' => null, - 'weight' => null - ], - [ - 'carrier_code' => 'USPS', - 'order_id' => $existingOrder->getId(), - 'title' => 'ground', - 'description' => null, - 'track_number' => '789654565', - 'parent_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'qty' => null, - 'weight' => null - ] - ], - 'items' => $items, - 'comments' => [ - [ - 'comment' => 'Shipment-related comment-1.', - 'is_customer_notified' => null, - 'is_visible_on_front' => null, - 'parent_id' => null - ], - [ - 'comment' => 'Shipment-related comment-2.', - 'is_customer_notified' => null, - 'is_visible_on_front' => null, - 'parent_id' => null - ], - [ - 'comment' => 'Shipment-related comment-3.', - 'is_customer_notified' => null, - 'is_visible_on_front' => null, - 'parent_id' => null - ] - - ] - ], - 'shipment data with multiple tracking' => [ - 'order_id' => $existingOrder->getId(), - 'entity_id' => null, - 'store_id' => null, - 'total_weight' => null, - 'total_qty' => null, - 'email_sent' => null, - 'customer_id' => null, - 'shipping_address_id' => null, - 'billing_address_id' => null, - 'shipment_status' => null, - 'increment_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'shipping_label' => null, - 'tracks' => [ - [ - 'carrier_code' => 'UPS', - 'order_id' => $existingOrder->getId(), - 'title' => 'ground', - 'description' => null, - 'track_number' => '12345678', - 'parent_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'qty' => null, - 'weight' => null - ], - [ - 'carrier_code' => 'UPS', - 'order_id' => $existingOrder->getId(), - 'title' => 'ground', - 'description' => null, - 'track_number' => '654563221', - 'parent_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'qty' => null, - 'weight' => null - ], - [ - 'carrier_code' => 'USPS', - 'order_id' => $existingOrder->getId(), - 'title' => 'ground', - 'description' => null, - 'track_number' => '789654565', - 'parent_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'qty' => null, - 'weight' => null - ] - ], - 'items' => $items, - 'comments' => [] - ], - 'shipment data with multiple comments' => [ - 'order_id' => $existingOrder->getId(), - 'entity_id' => null, - 'store_id' => null, - 'total_weight' => null, - 'total_qty' => null, - 'email_sent' => null, - 'customer_id' => null, - 'shipping_address_id' => null, - 'billing_address_id' => null, - 'shipment_status' => null, - 'increment_id' => null, - 'created_at' => null, - 'updated_at' => null, - 'shipping_label' => null, - 'tracks' => [], - 'items' => $items, - 'comments' => [ - [ - 'comment' => 'Shipment-related comment-1.', - 'is_customer_notified' => null, - 'is_visible_on_front' => null, - 'parent_id' => null - ], - [ - 'comment' => 'Shipment-related comment-2.', - 'is_customer_notified' => null, - 'is_visible_on_front' => null, - 'parent_id' => null - ], - [ - 'comment' => 'Shipment-related comment-3.', - 'is_customer_notified' => null, - 'is_visible_on_front' => null, - 'parent_id' => null - ] - - ] - ] - ]; - } - - /** - * Returns order by increment id. - * - * @param string $incrementId - * @return Order - */ - private function getOrder(string $incrementId): Order - { - return $this->objectManager->create(Order::class)->loadByIncrementId($incrementId); - } - - /** - * @return array - */ - private function getServiceInfo(): array - { - return [ + $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH, - 'httpMethod' => Request::HTTP_METHOD_POST, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_READ_NAME, @@ -316,5 +66,46 @@ private function getServiceInfo(): array 'operation' => self::SERVICE_READ_NAME . 'save', ], ]; + $data = [ + 'order_id' => $order->getId(), + 'entity_id' => null, + 'store_id' => null, + 'total_weight' => null, + 'total_qty' => null, + 'email_sent' => null, + 'customer_id' => null, + 'shipping_address_id' => null, + 'billing_address_id' => null, + 'shipment_status' => null, + 'increment_id' => null, + 'created_at' => null, + 'updated_at' => null, + 'shipping_label' => null, + 'tracks' => [ + [ + 'carrier_code' => 'UPS', + 'order_id' => $order->getId(), + 'title' => 'ground', + 'description' => null, + 'track_number' => '12345678', + 'parent_id' => null, + 'created_at' => null, + 'updated_at' => null, + 'qty' => null, + 'weight' => null + ] + ], + 'items' => $items, + 'comments' => [ + [ + 'comment' => 'Shipment-related comment.', + 'is_customer_notified' => null, + 'is_visible_on_front' => null, + 'parent_id' => null + ] + ], + ]; + $result = $this->_webApiCall($serviceInfo, ['entity' => $data]); + $this->assertNotEmpty($result); } } diff --git a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_bundle_shipped_separately.php b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_bundle_shipped_separately.php index e5f089ae9637c..b91d479cdf1ef 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_bundle_shipped_separately.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/_files/order_with_bundle_shipped_separately.php @@ -155,8 +155,6 @@ /** @var \Magento\Sales\Model\Order\Item $orderItem */ $orderItem = $objectManager->create(\Magento\Sales\Model\Order\Item::class); $orderItem->setProductId($product->getId()); -$orderItem->setSku($product->getSku()); -$orderItem->setName($product->getName()); $orderItem->setQtyOrdered(1); $orderItem->setBasePrice($product->getPrice()); $orderItem->setPrice($product->getPrice()); @@ -174,8 +172,6 @@ /** @var \Magento\Sales\Model\Order\Item $orderItem */ $orderItem = $objectManager->create(\Magento\Sales\Model\Order\Item::class); $orderItem->setProductId($productId); - $orderItem->setSku($selectedProduct->getSku()); - $orderItem->setName($selectedProduct->getName()); $orderItem->setQtyOrdered(1); $orderItem->setBasePrice($selectedProduct->getPrice()); $orderItem->setPrice($selectedProduct->getPrice()); From 7dcd8e31a54ddd4c7fa9a7dfa887f27c28b8e6a1 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Thu, 15 Oct 2020 15:54:38 -0500 Subject: [PATCH 14/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 5083d5475465e..2bebf6d5f0ae2 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -222,7 +222,11 @@ private function convertAddressArrayToAddressList(array $arrayList): AddressList { $laminasAddressList = new AddressList(); foreach ($arrayList as $address) { - $laminasAddressList->add($address->getEmail(), $address->getName()); + try { + $laminasAddressList->add($address->getEmail(), $address->getName()); + } catch (\InvalidArgumentException $e) { + continue; + } } return $laminasAddressList; From b09239f9750289ea63880933f0296332445f5d8c Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Thu, 15 Oct 2020 14:30:26 -0500 Subject: [PATCH 15/59] MC-38309: [CLOUD] empty cart after login - Fix guest session is destroyed after password reset --- .../Customer/Api/SessionCleanerInterface.php | 2 +- .../Customer/Controller/Account/EditPost.php | 10 +- .../Controller/Account/ResetPasswordPost.php | 9 +- .../Customer/Model/Session/SessionCleaner.php | 9 +- .../Customer/Model/AccountManagementTest.php | 134 ++++++++++++++++-- 5 files changed, 143 insertions(+), 21 deletions(-) diff --git a/app/code/Magento/Customer/Api/SessionCleanerInterface.php b/app/code/Magento/Customer/Api/SessionCleanerInterface.php index eb24712105f96..d8534f8b34e83 100644 --- a/app/code/Magento/Customer/Api/SessionCleanerInterface.php +++ b/app/code/Magento/Customer/Api/SessionCleanerInterface.php @@ -13,7 +13,7 @@ interface SessionCleanerInterface { /** - * Destroy all active customer sessions related to given customer id, including current session. + * Destroy all active customer sessions related to given customer except current session. * * @param int $customerId * @return void diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php index 04b5b72ae776b..6b59986f8ec5f 100644 --- a/app/code/Magento/Customer/Controller/Account/EditPost.php +++ b/app/code/Magento/Customer/Controller/Account/EditPost.php @@ -33,7 +33,8 @@ use Magento\Framework\Phrase; /** - * Class EditPost + * Customer edit account information controller + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class EditPost extends AbstractAccount implements CsrfAwareActionInterface, HttpPostActionInterface @@ -185,6 +186,7 @@ public function validateForCsrf(RequestInterface $request): ?bool * Change customer email or password action * * @return \Magento\Framework\Controller\Result\Redirect + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function execute() { @@ -217,6 +219,12 @@ public function execute() ); $this->dispatchSuccessEvent($customerCandidateDataObject); $this->messageManager->addSuccessMessage(__('You saved the account information.')); + // logout from current session if password changed. + if ($isPasswordChanged) { + $this->session->logout(); + $this->session->start(); + return $resultRedirect->setPath('customer/account/login'); + } return $resultRedirect->setPath('customer/account'); } catch (InvalidEmailOrPasswordException $e) { $this->messageManager->addErrorMessage($this->escaper->escapeHtml($e->getMessage())); diff --git a/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php index a127f2acf538f..1bb5aea9b1dc9 100644 --- a/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php +++ b/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php @@ -14,9 +14,7 @@ use Magento\Customer\Model\Customer\CredentialsValidator; /** - * Class ResetPasswordPost - * - * @package Magento\Customer\Controller\Account + * Customer reset password controller */ class ResetPasswordPost extends \Magento\Customer\Controller\AbstractAccount implements HttpPostActionInterface { @@ -91,6 +89,11 @@ public function execute() $resetPasswordToken, $password ); + // logout from current session if password changed. + if ($this->session->isLoggedIn()) { + $this->session->logout(); + $this->session->start(); + } $this->session->unsRpToken(); $this->messageManager->addSuccessMessage(__('You updated your password.')); $resultRedirect->setPath('*/*/login'); diff --git a/app/code/Magento/Customer/Model/Session/SessionCleaner.php b/app/code/Magento/Customer/Model/Session/SessionCleaner.php index 1423c94782535..5118c20329aaa 100644 --- a/app/code/Magento/Customer/Model/Session/SessionCleaner.php +++ b/app/code/Magento/Customer/Model/Session/SessionCleaner.php @@ -71,13 +71,6 @@ public function __construct( */ public function clearFor(int $customerId): void { - if ($this->sessionManager->isSessionExists()) { - //delete old session and move data to the new session - //use this instead of $this->sessionManager->regenerateId because last one doesn't delete old session - // phpcs:ignore Magento2.Functions.DiscouragedFunction - session_regenerate_id(true); - } - $sessionLifetime = $this->scopeConfig->getValue( Config::XML_PATH_COOKIE_LIFETIME, ScopeInterface::SCOPE_STORE @@ -89,6 +82,8 @@ public function clearFor(int $customerId): void $visitorCollection = $this->visitorCollectionFactory->create(); $visitorCollection->addFieldToFilter('customer_id', $customerId); $visitorCollection->addFieldToFilter('last_visit_at', ['from' => $activeSessionsTime]); + $visitorCollection->addFieldToFilter('session_id', ['neq' => $this->sessionManager->getSessionId()]); + /** @var \Magento\Customer\Model\Visitor $visitor */ foreach ($visitorCollection->getItems() as $visitor) { $sessionId = $visitor->getSessionId(); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index 6f2cf2d76bd11..3a16d3eafd6ce 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -14,6 +14,7 @@ use Magento\Framework\Exception\State\ExpiredException; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Session\SessionManagerInterface; +use Magento\Framework\Stdlib\DateTime; use Magento\Framework\Url as UrlBuilder; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; @@ -113,6 +114,10 @@ protected function tearDown(): void $customerRegistry->remove(1); $addressRegistry->remove(1); $addressRegistry->remove(2); + /** @var \Magento\Customer\Model\ResourceModel\Visitor $resourceModel */ + $resourceModel = $this->objectManager->get(\Magento\Customer\Model\ResourceModel\Visitor::class); + $resourceModel->getConnection()->delete($resourceModel->getMainTable()); + parent::tearDown(); } /** @@ -158,19 +163,52 @@ public function testChangePassword() { /** @var SessionManagerInterface $session */ $session = $this->objectManager->get(SessionManagerInterface::class); - $oldSessionId = $session->getSessionId(); - $session->setTestData('test'); + $time = time(); + + $session->start(); + $guessSessionId = $session->getSessionId(); + $this->createVisitorSession($guessSessionId); + $session->setTestData('guest_session_data'); + + // open new session + $activeSessionId = uniqid("active-$time-"); + $this->startNewSession($activeSessionId); + $this->createVisitorSession($activeSessionId, 1); + $session->setTestData('customer_session_data_1'); + + // open new session + $currentSessionId = uniqid("current-$time-"); + $this->startNewSession($currentSessionId); + $this->createVisitorSession($currentSessionId, 1); + $session->setTestData('customer_session_data_current'); + + // change password $this->accountManagement->changePassword('customer@example.com', 'password', 'new_Password123'); - - $this->assertTrue( - $oldSessionId !== $session->getSessionId(), - 'Customer session id wasn\'t regenerated after change password' + $this->assertEquals( + $currentSessionId, + $session->getSessionId(), + 'Current session was renewed' ); - $session->destroy(); - $session->setSessionId($oldSessionId); + // open customer active session + $this->startNewSession($activeSessionId); + $this->assertNull($session->getTestData(), 'Customer active session data wasn\'t cleaned up'); + + // open customer current session + $this->startNewSession($currentSessionId); + $this->assertEquals( + 'customer_session_data_current', + $session->getTestData(), + 'Customer current session data was cleaned up' + ); - $this->assertNull($session->getTestData(), 'Customer session data wasn\'t cleaned'); + // open guess session + $this->startNewSession($guessSessionId); + $this->assertEquals( + 'guest_session_data', + $session->getTestData(), + 'Guest session data was cleaned up' + ); $this->accountManagement->authenticate('customer@example.com', 'new_Password123'); } @@ -392,11 +430,58 @@ public function testValidateResetPasswordLinkTokenAmbiguous() */ public function testResetPassword() { + /** @var SessionManagerInterface $session */ + $session = $this->objectManager->get(SessionManagerInterface::class); + $time = time(); + + $session->start(); + $guessSessionId = $session->getSessionId(); + $this->createVisitorSession($guessSessionId); + $session->setTestData('guest_session_data'); + + // open new session + $activeSessionId = uniqid("active-$time-"); + $this->startNewSession($activeSessionId); + $this->createVisitorSession($activeSessionId, 1); + $session->setTestData('customer_session_data_1'); + + // open new session + $currentSessionId = uniqid("current-$time-"); + $this->startNewSession($currentSessionId); + $this->createVisitorSession($currentSessionId, 1); + $session->setTestData('customer_session_data_current'); + $resetToken = 'lsdj579slkj5987slkj595lkj'; $password = 'new_Password123'; $this->setResetPasswordData($resetToken, 'Y-m-d H:i:s'); $this->assertTrue($this->accountManagement->resetPassword('customer@example.com', $resetToken, $password)); + + $this->assertEquals( + $currentSessionId, + $session->getSessionId(), + 'Current session was renewed' + ); + + // open customer active session + $this->startNewSession($activeSessionId); + $this->assertNull($session->getTestData(), 'Customer active session data wasn\'t cleaned up'); + + // open customer current session + $this->startNewSession($currentSessionId); + $this->assertEquals( + 'customer_session_data_current', + $session->getTestData(), + 'Customer current session data was cleaned up' + ); + + // open guess session + $this->startNewSession($guessSessionId); + $this->assertEquals( + 'guest_session_data', + $session->getTestData(), + 'Guest session data was cleaned up' + ); } /** @@ -727,4 +812,35 @@ protected function setResetPasswordData( $customerModel->setRpTokenCreatedAt(date($date)); $customerModel->save(); } + + /** + * @param string $sessionId + */ + private function startNewSession(string $sessionId): void + { + /** @var SessionManagerInterface $session */ + $session = $this->objectManager->get(SessionManagerInterface::class); + // close session and cleanup session variable + $session->writeClose(); + $session->clearStorage(); + // open new session + $session->setSessionId($sessionId); + $session->start(); + } + + /** + * @param string $sessionId + * @param int|null $customerId + * @return Visitor + */ + private function createVisitorSession(string $sessionId, ?int $customerId = null): Visitor + { + /** @var Visitor $visitor */ + $visitor = Bootstrap::getObjectManager()->create(Visitor::class); + $visitor->setCustomerId($customerId); + $visitor->setSessionId($sessionId); + $visitor->setLastVisitAt((new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT)); + $visitor->save(); + return $visitor; + } } From ab0f3177ab48775b6de76cc2be4d7b89b593dfdc Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Fri, 16 Oct 2020 11:55:32 -0500 Subject: [PATCH 16/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- .../Framework/Mail/TransportBuilderTest.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Mail/TransportBuilderTest.php b/dev/tests/integration/testsuite/Magento/Framework/Mail/TransportBuilderTest.php index 9dc8aa91237d8..47c8da84902d4 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Mail/TransportBuilderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Mail/TransportBuilderTest.php @@ -116,4 +116,84 @@ public function emailDataProvider(): array ] ]; } + + /** + * Test if invalid email in the queue will not fail the entire queue from being sent + * + * @magentoDataFixture Magento/Email/Model/_files/email_template.php + * @magentoDbIsolation enabled + * + * @param string|array $emails + * @dataProvider invalidEmailDataProvider + * @throws LocalizedException + */ + public function testAddToInvalidEmailInTheQueue($emails) + { + $template = $this->template->load('email_exception_fixture', 'template_code'); + $templateId = $template->getId(); + + switch ($template->getType()) { + case TemplateTypesInterface::TYPE_TEXT: + $templateType = MimeInterface::TYPE_TEXT; + break; + + case TemplateTypesInterface::TYPE_HTML: + $templateType = MimeInterface::TYPE_HTML; + break; + + default: + $templateType = ''; + $this->fail('Unsupported Mime Type'); + } + + $this->builder->setTemplateModel(BackendTemplate::class); + + $vars = ['reason' => 'Reason', 'customer' => 'Customer']; + $options = ['area' => 'frontend', 'store' => 1]; + $this->builder->setTemplateIdentifier($templateId)->setTemplateVars($vars)->setTemplateOptions($options); + + $allEmails = $emails[0]; + $validOnlyEmails = $emails[1]; + + foreach ($allEmails as $email) { + $this->builder->addTo($email); + } + + /** @var EmailMessage $emailMessage */ + $emailMessage = $this->builder->getTransport()->getMessage(); + $this->assertStringContainsStringIgnoringCase($templateType, $emailMessage->getHeaders()['Content-Type']); + + $resultEmails = []; + /** @var Address $toAddress */ + foreach ($emailMessage->getTo() as $address) { + $resultEmails[] = $address->getEmail(); + } + + $this->assertEquals($validOnlyEmails, $resultEmails); + } + + /** + * @return array + */ + public function invalidEmailDataProvider(): array + { + return [ + [ + [ + [ + 'billy.everything@someserver.com', + 'billy.everythingsomeserver.com', + 'billy.everything2@someserver.com', + 'billy.everythin2gsomeserver.com', + 'billy.everything3@someserver.com' + ], + [ + 'billy.everything@someserver.com', + 'billy.everything2@someserver.com', + 'billy.everything3@someserver.com' + ] + ] + ] + ]; + } } From 3de90f72bcfc208e07fa58f79e6be7579a73bc60 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 19 Oct 2020 12:14:35 -0500 Subject: [PATCH 17/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- .../Magento/Framework/Mail/EmailMessage.php | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 2bebf6d5f0ae2..184f64e902bc9 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -7,10 +7,12 @@ namespace Magento\Framework\Mail; +use Laminas\Mail\Exception\InvalidArgumentException as LaminasInvalidArgumentException; use Magento\Framework\Mail\Exception\InvalidArgumentException; use Laminas\Mail\Address as LaminasAddress; use Laminas\Mail\AddressList; use Laminas\Mime\Message as LaminasMimeMessage; +use Psr\Log\LoggerInterface; /** * Magento Framework Email message @@ -27,6 +29,11 @@ class EmailMessage extends Message implements EmailMessageInterface */ private $addressFactory; + /** + * @var LoggerInterface + */ + private $logger; + /** * @param MimeMessageInterface $body * @param array $to @@ -39,8 +46,7 @@ class EmailMessage extends Message implements EmailMessageInterface * @param Address|null $sender * @param string|null $subject * @param string|null $encoding - * @throws InvalidArgumentException - * + * @param LoggerInterface $logger * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -56,10 +62,12 @@ public function __construct( ?array $replyTo = null, ?Address $sender = null, ?string $subject = '', - ?string $encoding = 'utf-8' + ?string $encoding = 'utf-8', + LoggerInterface $logger ) { parent::__construct($encoding); $mimeMessage = new LaminasMimeMessage(); + $this->logger = $logger; $mimeMessage->setParts($body->getParts()); $this->zendMessage->setBody($mimeMessage); if ($subject) { @@ -224,7 +232,11 @@ private function convertAddressArrayToAddressList(array $arrayList): AddressList foreach ($arrayList as $address) { try { $laminasAddressList->add($address->getEmail(), $address->getName()); - } catch (\InvalidArgumentException $e) { + } catch (LaminasInvalidArgumentException $e) { + $this->logger->warning( + 'Could not add an invalid email address to the mailing queue', + ['exception' => $e] + ); continue; } } From ceb44748510f39c4782220c9f907d77247a2e31e Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 19 Oct 2020 15:11:15 -0500 Subject: [PATCH 18/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 184f64e902bc9..f2c4856af4909 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Mail; use Laminas\Mail\Exception\InvalidArgumentException as LaminasInvalidArgumentException; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Mail\Exception\InvalidArgumentException; use Laminas\Mail\Address as LaminasAddress; use Laminas\Mail\AddressList; @@ -30,7 +31,7 @@ class EmailMessage extends Message implements EmailMessageInterface private $addressFactory; /** - * @var LoggerInterface + * @var LoggerInterface|null */ private $logger; @@ -46,7 +47,7 @@ class EmailMessage extends Message implements EmailMessageInterface * @param Address|null $sender * @param string|null $subject * @param string|null $encoding - * @param LoggerInterface $logger + * @param LoggerInterface|null $logger * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -63,11 +64,11 @@ public function __construct( ?Address $sender = null, ?string $subject = '', ?string $encoding = 'utf-8', - LoggerInterface $logger + ?LoggerInterface $logger = null ) { parent::__construct($encoding); $mimeMessage = new LaminasMimeMessage(); - $this->logger = $logger; + $this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class); $mimeMessage->setParts($body->getParts()); $this->zendMessage->setBody($mimeMessage); if ($subject) { From 0d40b6c42b589ea8310a153680f0dda4224056ce Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 19 Oct 2020 15:48:09 -0500 Subject: [PATCH 19/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index f2c4856af4909..46ba8c118232b 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -51,6 +51,7 @@ class EmailMessage extends Message implements EmailMessageInterface * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ public function __construct( MimeMessageInterface $body, From c66199ceb55d5f338c6950315e00ed6c681e63d9 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 19 Oct 2020 15:57:40 -0500 Subject: [PATCH 20/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 46ba8c118232b..726c76ee96850 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -48,6 +48,7 @@ class EmailMessage extends Message implements EmailMessageInterface * @param string|null $subject * @param string|null $encoding * @param LoggerInterface|null $logger + * @throws InvalidArgumentException * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) From 37d086856e3dbd0169ea8c3d7c38db944b3b34c4 Mon Sep 17 00:00:00 2001 From: Roman Flowers Date: Mon, 19 Oct 2020 17:54:15 -0500 Subject: [PATCH 21/59] MC-38337: [Magento Cloud] Repeat Email Reminders only go to a limited number of customers --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 726c76ee96850..53ea805889db2 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -17,6 +17,8 @@ /** * Magento Framework Email message + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class EmailMessage extends Message implements EmailMessageInterface { @@ -52,7 +54,6 @@ class EmailMessage extends Message implements EmailMessageInterface * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ public function __construct( MimeMessageInterface $body, From fcaa729c390c4a2a4d62bd59a8c14bf21c24e8f1 Mon Sep 17 00:00:00 2001 From: Sudheer S Date: Tue, 20 Oct 2020 12:17:00 +0530 Subject: [PATCH 22/59] 30349: Product filter with category_id does not work as expected - added API functional test --- .../GraphQl/Catalog/ProductSearchTest.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php index f755a1a1e0282..3b2febe44b215 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php @@ -1448,11 +1448,12 @@ public function testFilterProductsForExactMatchingName() */ public function testFilteringForProductsFromMultipleCategories() { + $categoriesIds = ["4","5","12"]; $query = <<graphQlQuery($query); /** @var ProductRepositoryInterface $productRepository */ $this->assertEquals(3, $response['products']['total_count']); + $actualProducts = []; + foreach ($categoriesIds as $categoriesId) { + /** @var CategoryLinkManagement $productLinks */ + $productLinks = ObjectManager::getInstance()->get(CategoryLinkManagement::class); + $links = $productLinks->getAssignedProducts($categoriesId); + $links = array_reverse($links); + foreach ($links as $linkProduct) { + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product = $productRepository->get($linkProduct->getSku()); + $actualProducts[$linkProduct->getSku()] = $product->getName(); + } + } + $this->assertEquals(array_column($response['products']['items'],"name","sku"), $actualProducts); } /** From b07c48320f301e6c166266ba437413161b6cc7d9 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun Date: Tue, 20 Oct 2020 12:59:52 +0300 Subject: [PATCH 23/59] MC-38488: [MFTF] AdminMediaGalleryAssertUsedInLinkBlocksGridTest failed because of bad design --- ...eryAssertImageUsedInLinkBlocksGridTest.xml | 90 +++++++++++++++++++ ...aGalleryAssertUsedInLinkBlocksGridTest.xml | 4 +- ...nhancedMediaGalleryImageActionsSection.xml | 2 +- 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml new file mode 100644 index 0000000000000..c25e55cd30461 --- /dev/null +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml @@ -0,0 +1,90 @@ + + + + + + + + + + <stories value="Story 58: User sees entities where asset is used in" /> + <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951848"/> + <description value="User filters assets used in blocks"/> + <severity value="CRITICAL"/> + <group value="media_gallery_ui"/> + </annotations> + <before> + <createData entity="_defaultBlock" stepKey="block" /> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> + </before> + <after> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> + <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterTest"> + <argument name="tags" value="block_html"/> + </actionGroup> + </after> + + <actionGroup ref="NavigateToCreatedCMSBlockPageActionGroup" stepKey="navigateToCreatedCMSBlockPage"> + <argument name="CMSBlockPage" value="$$block$$"/> + </actionGroup> + <click selector="{{CmsWYSIWYGSection.InsertImageBtn}}" stepKey="clickInsertImageIcon" /> + <waitForPageLoad stepKey="waitForInitialPageLoad" /> + <waitForPageLoad stepKey="waitForSecondaryPageLoad" /> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> + <actionGroup ref="AdminMediaGalleryOpenNewFolderFormActionGroup" stepKey="openNewFolderForm"/> + <actionGroup ref="AdminMediaGalleryCreateNewFolderActionGroup" stepKey="createNewFolder"> + <argument name="name" value="blockImage"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryAssertFolderNameActionGroup" stepKey="assertNewFolderCreated"> + <argument name="name" value="blockImage"/> + </actionGroup> + <waitForPageLoad stepKey="waitForGridToLoadAfterNewFolderCreated"/> + <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadImage"> + <argument name="image" value="ImageUpload3"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickImageInGridActionGroup" stepKey="selectContentImageInGrid"> + <argument name="imageName" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickAddSelectedActionGroup" stepKey="clickAddSelectedContentImage"/> + <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="saveBlock"/> + + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openStandaloneMediaGallery"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolder"> + <argument name="name" value="blockImage"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetails"/> + <actionGroup ref="AdminEnhancedMediaGalleryClickEntityUsedInActionGroup" stepKey="clickUsedInBlocks"> + <argument name="entityName" value="Blocks"/> + </actionGroup> + <wait time="5" stepKey="waitForAssertLoads"/> + <reloadPage stepKey="reloadBlocksGridPage"/> + <waitForPageLoad stepKey="waitForBlocksGridPageLoad"/> + <actionGroup ref="AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup" stepKey="assertFilterApplied"> + <argument name="filterPlaceholder" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilterInBlocksGrid"/> + + <deleteData createDataKey="block" stepKey="deleteBlock"/> + + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultViewAgain"/> + <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolderAgain"> + <argument name="name" value="blockImage"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetailsToVerifyEmptyUsedIn"/> + <actionGroup ref="AssertAdminEnhancedMediaGalleryUsedInSectionNotDisplayedActionGroup" stepKey="assertThereIsNoUsedInSection"/> + <actionGroup ref="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup" stepKey="closeImageDetails"/> + + <actionGroup ref="AdminMediaGalleryFolderDeleteActionGroup" stepKey="deleteFolder"/> + <actionGroup ref="AdminMediaGalleryAssertFolderDoesNotExistActionGroup" stepKey="assertFolderWasDeleted"> + <argument name="name" value="blockImage"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml index c850d09cd8a03..69d0c191fd146 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml @@ -7,11 +7,11 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminMediaGalleryAssertUsedInLinkBlocksGridTest"> + <test name="AdminMediaGalleryAssertUsedInLinkBlocksGridTest" deprecated="Use AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest instead"> <annotations> <features value="AdminMediaGalleryUsedInBlocksFilter"/> <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1168"/> - <title value="Used in blocks link"/> + <title value="Deprecated. Used in blocks link"/> <stories value="Story 58: User sees entities where asset is used in" /> <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951848"/> <description value="User filters assets used in blocks"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml index f36fca88dc760..fb813bd65c9bf 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml @@ -10,7 +10,7 @@ <section name="AdminEnhancedMediaGalleryImageActionsSection"> <element name="openContextMenu" type="button" selector=".three-dots"/> <element name="contextMenuItem" type="block" selector="//div[@class='media-gallery-image']//ul[@class='action-menu _active']//li//a[@class='action-menu-item']"/> - <element name="viewDetails" type="button" selector="[data-ui-id='action-image-details']"/> + <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[@class='action-menu-item' and contains(text(), 'View Details')]"/> <element name="delete" type="button" selector="[data-ui-id='action-delete']"/> <element name="edit" type="button" selector="[data-ui-id='action-edit']"/> <element name="imageInGrid" type="button" selector="//li[@data-ui-id='title'and text()='{{imageTitle}}']/parent::*/parent::*/parent::div//img[@class='media-gallery-image-column']" parameterized="true"/> From 09cd013f4f58d2541b61af3e67f5486ad89b2872 Mon Sep 17 00:00:00 2001 From: Sudheer S <sudheers@kensium.com> Date: Tue, 20 Oct 2020 16:35:29 +0530 Subject: [PATCH 24/59] 30349: Product filter with category_id does not work as expected - added API functional test --- .../testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php index 3b2febe44b215..1fecc1a76c176 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php @@ -1492,7 +1492,8 @@ public function testFilteringForProductsFromMultipleCategories() $actualProducts[$linkProduct->getSku()] = $product->getName(); } } - $this->assertEquals(array_column($response['products']['items'],"name","sku"), $actualProducts); + $expectedProducts = array_column($response['products']['items'],"name","sku"); + $this->assertEquals($expectedProducts, $actualProducts); } /** From afe3cd9d4c7f97a8097d08f4636cd99fa50c5671 Mon Sep 17 00:00:00 2001 From: Sudheer S <sudheers@kensium.com> Date: Wed, 21 Oct 2020 11:59:28 +0530 Subject: [PATCH 25/59] 30349: Product filter with category_id does not work as expected - added API functional test --- .../testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php index 1fecc1a76c176..b0d7141d55589 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchTest.php @@ -1492,7 +1492,7 @@ public function testFilteringForProductsFromMultipleCategories() $actualProducts[$linkProduct->getSku()] = $product->getName(); } } - $expectedProducts = array_column($response['products']['items'],"name","sku"); + $expectedProducts = array_column($response['products']['items'], "name", "sku"); $this->assertEquals($expectedProducts, $actualProducts); } From 5df1d69445c7dd3a4d56e6cff66fecd824d93620 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Wed, 21 Oct 2020 10:20:46 +0300 Subject: [PATCH 26/59] MC-38488: [MFTF] AdminMediaGalleryAssertUsedInLinkBlocksGridTest failed because of bad design --- .../Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml | 3 +++ .../Section/AdminEnhancedMediaGalleryImageActionsSection.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml index 69d0c191fd146..b360d958aee33 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkBlocksGridTest.xml @@ -17,6 +17,9 @@ <description value="User filters assets used in blocks"/> <severity value="CRITICAL"/> <group value="media_gallery_ui"/> + <skip> + <issueId value="DEPRECATED">Use AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest instead</issueId> + </skip> </annotations> <before> <createData entity="_defaultBlock" stepKey="block" /> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml index fb813bd65c9bf..a8e9feaa2d623 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml @@ -10,7 +10,7 @@ <section name="AdminEnhancedMediaGalleryImageActionsSection"> <element name="openContextMenu" type="button" selector=".three-dots"/> <element name="contextMenuItem" type="block" selector="//div[@class='media-gallery-image']//ul[@class='action-menu _active']//li//a[@class='action-menu-item']"/> - <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[@class='action-menu-item' and contains(text(), 'View Details')]"/> + <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[@class='action-menu-item' and contains(text(), 'View Details')]" timeout="30" /> <element name="delete" type="button" selector="[data-ui-id='action-delete']"/> <element name="edit" type="button" selector="[data-ui-id='action-edit']"/> <element name="imageInGrid" type="button" selector="//li[@data-ui-id='title'and text()='{{imageTitle}}']/parent::*/parent::*/parent::div//img[@class='media-gallery-image-column']" parameterized="true"/> From 3176d9d703a7859646c2543a564cb58c6c1ac99d Mon Sep 17 00:00:00 2001 From: engcom-Echo <engcom-vendorworker-echo@adobe.com> Date: Wed, 21 Oct 2020 15:19:12 +0300 Subject: [PATCH 27/59] MC-37213: [MFTF] AdminMediaGalleryCatalogUiUsedInProductFilterTest is flaky --- .../AdminDisableWYSIWYGActionGroup.xml | 2 +- .../AdminEnableWYSIWYGActionGroup.xml | 2 +- .../Cms/Test/Mftf/Data/WysiwygConfigData.xml | 2 +- ...alleryFilterPlaceHolderGridActionGroup.xml | 2 + ...leryCatalogUiUsedInProductFilterOnTest.xml | 79 +++++++++++++++++++ ...alleryCatalogUiUsedInProductFilterTest.xml | 7 +- ...nhancedMediaGalleryImageActionsSection.xml | 2 +- .../Test/Mftf/Suite/MediaGalleryUiSuite.xml | 12 +-- .../web/js/grid/filters/elements/ui-select.js | 4 +- 9 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminDisableWYSIWYGActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminDisableWYSIWYGActionGroup.xml index 7e035a47824ee..8407860959184 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminDisableWYSIWYGActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminDisableWYSIWYGActionGroup.xml @@ -13,6 +13,6 @@ <description>Runs bin/magento command to disable WYSIWYG</description> </annotations> - <magentoCLI stepKey="disableWYSIWYG" command="config:set cms/wysiwyg/enabled disabled"/> + <magentoCLI command="config:set {{WysiwygDisabledByDefault.path}} {{WysiwygDisabledByDefault.value}}" stepKey="disableWYSIWYG"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminEnableWYSIWYGActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminEnableWYSIWYGActionGroup.xml index 6c9b439e2941b..58c219092d85e 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminEnableWYSIWYGActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminEnableWYSIWYGActionGroup.xml @@ -13,6 +13,6 @@ <description>Runs bin/magento command to enable WYSIWYG</description> </annotations> - <magentoCLI stepKey="enableWYSIWYG" command="config:set cms/wysiwyg/enabled enabled"/> + <magentoCLI command="config:set {{WysiwygEnabledByDefault.path}} {{WysiwygEnabledByDefault.value}}" stepKey="enableWYSIWYG"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Data/WysiwygConfigData.xml b/app/code/Magento/Cms/Test/Mftf/Data/WysiwygConfigData.xml index ea5e90383511c..66f2983140b45 100644 --- a/app/code/Magento/Cms/Test/Mftf/Data/WysiwygConfigData.xml +++ b/app/code/Magento/Cms/Test/Mftf/Data/WysiwygConfigData.xml @@ -16,7 +16,7 @@ <entity name="WysiwygDisabledByDefault"> <data key="path">cms/wysiwyg/enabled</data> <data key="scope_id">0</data> - <data key="value">hidden</data> + <data key="value">disabled</data> </entity> <entity name="WysiwygTinyMCE3Enable" deprecated="Use WysiwygTinyMCE4Enable instead"> <data key="path">cms/wysiwyg/editor</data> diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup.xml index e21fa89965391..32065da7bb1e7 100644 --- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup.xml +++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/ActionGroup/AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup.xml @@ -15,6 +15,8 @@ <argument name="filterPlaceholder" type="string"/> </arguments> + <waitForPageLoad stepKey="waitVisibleFilter"/> + <waitForElementVisible selector="{{AdminProductGridFilterSection.enabledFilters}}" stepKey="waitForRequest"/> <see selector="{{AdminProductGridFilterSection.enabledFilters}}" userInput="{{filterPlaceholder}}" stepKey="seeFilter"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml new file mode 100644 index 0000000000000..32a07d6f6273f --- /dev/null +++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml @@ -0,0 +1,79 @@ +<?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="AdminMediaGalleryCatalogUiUsedInProductFilterOnTest"> + <annotations> + <features value="MediaGalleryCatalogUi"/> + <stories value="Story 58 - User sees entities where asset is used in" /> + <title value="User can open the product entity the asset is associated"/> + <description value="User filters assets used in products"/> + <severity value="CRITICAL"/> + <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/943908/scenarios/4523889"/> + <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1503"/> + <group value="media_gallery_ui"/> + </annotations> + + <before> + <magentoCLI command="config:set {{WysiwygEnabledByDefault.path}} {{WysiwygEnabledByDefault.value}}" stepKey="enableWYSIWYG"/> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + </before> + + <after> + <magentoCLI command="config:set {{WysiwygDisabledByDefault.path}} {{WysiwygDisabledByDefault.value}}" stepKey="disableWYSIWYG"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetailsToAssertEmptyUsedIn"/> + <actionGroup ref="AssertAdminEnhancedMediaGalleryUsedInSectionNotDisplayedActionGroup" stepKey="assertThereIsNoUsedInSection"/> + <actionGroup ref="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup" stepKey="closeDetails"/> + + <actionGroup ref="AdminEnhancedMediaGalleryEnableMassActionModeActionGroup" stepKey="enableMassActionToDeleteImages"/> + <actionGroup ref="AdminEnhancedMediaGallerySelectImageForMassActionActionGroup" stepKey="selectFirstImageToDelete"> + <argument name="imageName" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryClickDeleteImagesButtonActionGroup" stepKey="clickDeleteSelectedButton"/> + <actionGroup ref="AdminEnhancedMediaGalleryConfirmDeleteImagesActionGroup" stepKey="deleteImages"/> + + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView2"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <actionGroup ref="AdminProductPageOpenByIdActionGroup" stepKey="goToProductEditPage"> + <argument name="productId" value="$createProduct.id$"/> + </actionGroup> + <actionGroup ref="AdminOpenMediaGalleryTinyMce4ActionGroup" stepKey="openMediaGalleryFromWysiwyg"/> + <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadImage"> + <argument name="image" value="ImageUpload3"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickImageInGridActionGroup" stepKey="selectContentImageInGrid"> + <argument name="imageName" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickAddSelectedActionGroup" stepKey="clickAddSelectedContentImage"/> + <actionGroup ref="AdminMediaGalleryClickOkButtonTinyMce4ActionGroup" stepKey="clickOkButton"/> + <actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/> + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openStandaloneMediaGallery"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> + <actionGroup ref="AdminEnhancedMediaGalleryExpandFilterActionGroup" stepKey="expandFilters"/> + <actionGroup ref="AdminEnhancedMediaGallerySelectUsedInFilterActionGroup" stepKey="setUsedInFilter"> + <argument name="filterName" value="Used in Products"/> + <argument name="optionName" value="$createProduct.name$"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryApplyFiltersActionGroup" stepKey="applyFilters"/> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetails"/> + <actionGroup ref="AdminEnhancedMediaGalleryClickEntityUsedInActionGroup" stepKey="clickUsedInProducts"> + <argument name="entityName" value="Products"/> + </actionGroup> + <actionGroup ref="AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup" stepKey="assertFilterApplied"> + <argument name="filterPlaceholder" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersOnProductGrid"/> + + </test> +</tests> diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml index a66009e9d2045..34d51f6533ef5 100644 --- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml +++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterTest.xml @@ -7,16 +7,19 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminMediaGalleryCatalogUiUsedInProductFilterTest"> + <test name="AdminMediaGalleryCatalogUiUsedInProductFilterTest" deprecated="Use AdminMediaGalleryCatalogUiUsedInProductFilterOnTest instead"> <annotations> <features value="AdminMediaGalleryUsedInProductsFilter"/> <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1503"/> - <title value="User can open product entity the asset is associated"/> + <title value="Deprecated. User can open product entity the asset is associated"/> <stories value="Story 58: User sees entities where asset is used in" /> <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/943908/scenarios/4523889"/> <description value="User filters assets used in products"/> <severity value="CRITICAL"/> <group value="media_gallery_ui"/> + <skip> + <issueId value="DEPRECATED">Use AdminMediaGalleryCatalogUiUsedInProductFilterOnTest instead</issueId> + </skip> </annotations> <before> <magentoCLI command="config:set cms/wysiwyg/enabled enabled" stepKey="enableWYSIWYG"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml index f36fca88dc760..32282f4f5e8ca 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml @@ -10,7 +10,7 @@ <section name="AdminEnhancedMediaGalleryImageActionsSection"> <element name="openContextMenu" type="button" selector=".three-dots"/> <element name="contextMenuItem" type="block" selector="//div[@class='media-gallery-image']//ul[@class='action-menu _active']//li//a[@class='action-menu-item']"/> - <element name="viewDetails" type="button" selector="[data-ui-id='action-image-details']"/> + <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[text()='View Details']"/> <element name="delete" type="button" selector="[data-ui-id='action-delete']"/> <element name="edit" type="button" selector="[data-ui-id='action-edit']"/> <element name="imageInGrid" type="button" selector="//li[@data-ui-id='title'and text()='{{imageTitle}}']/parent::*/parent::*/parent::div//img[@class='media-gallery-image-column']" parameterized="true"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml index e81dc807d0f48..bda9b6ad08e43 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml @@ -11,16 +11,12 @@ <suite name="MediaGalleryUiSuite"> <before> <actionGroup ref="AdminDisableWYSIWYGActionGroup" stepKey="disableWYSIWYG" /> - <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <actionGroup ref="AdminMediaGalleryEnhancedEnableActionGroup" stepKey="enableEnhancedMediaGallery"> - <argument name="enabled" value="1"/> - </actionGroup> - <actionGroup ref="AdminMediaGalleryRenditionsEnableActionGroup" stepKey="enableMediaGalleryRenditions"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> + <magentoCLI command="config:set {{MediaGalleryConfigDataEnabled.path}} {{MediaGalleryConfigDataEnabled.value}}" stepKey="enableEnhancedMediaGallery"/> + <magentoCLI command="config:set {{MediaGalleryRenditionsDataEnabled.path}} {{MediaGalleryRenditionsDataEnabled.value}}" stepKey="enableMediaGalleryRenditions"/> </before> <after> - <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> - <actionGroup ref="AdminMediaGalleryEnhancedEnableActionGroup" stepKey="disableEnhancedMediaGallery"/> + <magentoCLI command="config:set {{MediaGalleryRenditionsDataDisabled.path}} {{MediaGalleryRenditionsDataDisabled.value}}" stepKey="disableMediaGalleryRenditions"/> + <magentoCLI command="config:set {{MediaGalleryConfigDataDisabled.path}} {{MediaGalleryConfigDataDisabled.value}}" stepKey="disableEnhancedMediaGallery"/> <actionGroup ref="AdminEnableWYSIWYGActionGroup" stepKey="enableWYSIWYG" /> </after> <include> diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js index a913f3fa4a042..cddcc7d49ffe8 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js @@ -18,13 +18,15 @@ define([ loadedOption: [], validationLoading: true, imports: { + applied: '${ $.filterChipsProvider }:applied', activeIndex: '${ $.bookmarkProvider }:activeIndex' }, modules: { filterChips: '${ $.filterChipsProvider }' }, listens: { - activeIndex: 'validateInitialValue' + activeIndex: 'validateInitialValue', + applied: 'validateInitialValue' } }, From 59b7ba8a5845ea8964d62e1ed9c28d18fc5925a9 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 22 Oct 2020 10:56:30 +0300 Subject: [PATCH 28/59] MC-38589: [MFTF] AdminEnhancedMediaGalleryVerifyAssetFilterTest failed because of bad design --- .../TinyMCESection/MediaGallerySection.xml | 1 + ...ediaGalleryDeletedAllImagesActionGroup.xml | 30 ++++++++ ...ediaGalleryClickAddSelectedActionGroup.xml | 6 +- ...ediaGalleryFromTinyMce4IconActionGroup.xml | 4 +- .../Test/Mftf/Helper/MediaGalleryUiHelper.php | 77 +++++++++++++++++++ ...nEnhancedMediaGalleryMassActionSection.xml | 1 + .../Section/AdminMediaGalleryGridSection.xml | 2 +- .../AdminMediaGalleryMessagesSection.xml | 13 ++++ ...ancedMediaGalleryVerifyAssetFilterTest.xml | 7 +- ...cedMediaGalleryVerifyFilterByAssetTest.xml | 75 ++++++++++++++++++ 10 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection/MediaGallerySection.xml b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection/MediaGallerySection.xml index 725d050554f2d..212035fbc575a 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection/MediaGallerySection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/TinyMCESection/MediaGallerySection.xml @@ -36,5 +36,6 @@ <element name="checkIfWysiwygArrowExpand" type="button" selector="//li[@id='d3lzaXd5Zw--' and contains(@class,'jstree-closed')]"/> <element name="confirmDelete" type="button" selector=".action-primary.action-accept"/> <element name="imageBlockByName" type="block" selector="//div[@data-row='file'][contains(., '{{imageName}}')]" parameterized="true"/> + <element name="insertEditImageModalWindow" type="block" selector=".mce-floatpanel.mce-window[aria-label='Insert/edit image']"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml new file mode 100644 index 0000000000000..f77521879c8ea --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup"> + <annotations> + <description>Open Media Gallery page and delete all images</description> + </annotations> + + <amOnPage url="{{AdminStandaloneMediaGalleryPage.url}}" stepKey="openMediaGalleryPage"/> + <!-- It sometimes is loading too long for default 10s --> + <waitForPageLoad time="60" stepKey="waitForPageFullyLoaded"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingFilters"/> + <helper class="\Magento\MediaGalleryUi\Test\Mftf\Helper\MediaGalleryUiHelper" method="deleteAllImagesUsingMassAction" stepKey="deleteAllImagesUsingMassAction"> + <argument name="emptyRow">{{AdminMediaGalleryGridSection.noDataMessage}}</argument> + <argument name="deleteImagesButton">{{AdminEnhancedMediaGalleryMassActionSection.deleteImages}}</argument> + <argument name="checkImage">{{AdminEnhancedMediaGalleryMassActionSection.massActionCheckboxAll}}</argument> + <argument name="deleteSelectedButton">{{AdminEnhancedMediaGalleryMassActionSection.deleteSelected}}</argument> + <argument name="modalAcceptButton">{{AdminEnhancedMediaGalleryDeleteModalSection.confirmDelete}}</argument> + <argument name="successMessageContainer">{{AdminMediaGalleryMessagesSection.success}}</argument> + <argument name="successMessage">been successfully deleted</argument> + </helper> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml index 45ab4dc4538e0..f575e346a8ca0 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml @@ -10,8 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminMediaGalleryClickAddSelectedActionGroup"> <waitForElementVisible selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="waitForAddSelectedButton"/> - <click selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="ClickAddSelected"/> - <wait time="5" stepKey="waitForImageToBeAdded"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskDisappear"/> + <click selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="clickAddSelected"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <waitForElementVisible selector="{{MediaGallerySection.insertEditImageModalWindow}}" stepKey="waitForInsertEditImageWindow"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromTinyMce4IconActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromTinyMce4IconActionGroup.xml index 3143b4ff24fb4..e4fb6aec5c152 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromTinyMce4IconActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromTinyMce4IconActionGroup.xml @@ -11,8 +11,8 @@ <annotations> <description>Opens Enhanced MediaGallery from category page by tyniMce4 image icon</description> </annotations> - - <click selector="{{AdminCategoryContentSection.sectionHeader}}" stepKey="clickExpandContent"/> + + <conditionalClick selector="{{AdminCategoryContentSection.sectionHeader}}" dependentSelector="{{AdminCategoryContentSection.uploadButton}}" visible="false" stepKey="clickExpandContent"/> <waitForElementVisible selector="{{TinyMCESection.TinyMCE4}}" stepKey="waitForTinyMCE4" /> <click selector="{{TinyMCESection.InsertImageIcon}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForPageLoad" /> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php b/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php new file mode 100644 index 0000000000000..4059a8460bb51 --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MediaGalleryUi\Test\Mftf\Helper; + +use Facebook\WebDriver\Remote\RemoteWebDriver as FacebookWebDriver; +use Facebook\WebDriver\Remote\RemoteWebElement; +use Facebook\WebDriver\WebDriverBy; +use Magento\FunctionalTestingFramework\Helper\Helper; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; + +/** + * Class for MFTF helpers for MediaGalleryUi module. + */ +class MediaGalleryUiHelper extends Helper +{ + /** + * Delete all images using mass action. + * + * @param string $emptyRow + * @param string $deleteImagesButton + * @param string $checkImage + * @param string $deleteSelectedButton + * @param string $modalAcceptButton + * @param string $successMessageContainer + * @param string $successMessage + * + * @return void + */ + public function deleteAllImagesUsingMassAction( + string $emptyRow, + string $deleteImagesButton, + string $checkImage, + string $deleteSelectedButton, + string $modalAcceptButton, + string $successMessageContainer, + string $successMessage + ): void { + try { + /** @var MagentoWebDriver $webDriver */ + $magentoWebDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + /** @var FacebookWebDriver $webDriver */ + $webDriver = $magentoWebDriver->webDriver; + $rows = $webDriver->findElements(WebDriverBy::cssSelector($emptyRow)); + while (empty($rows)) { + $magentoWebDriver->click($deleteImagesButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($deleteSelectedButton, 10); + + // Check all images + /** @var RemoteWebElement[] $images */ + $imagesCheckboxes = $webDriver->findElements(WebDriverBy::cssSelector($checkImage)); + /** @var RemoteWebElement $image */ + foreach ($imagesCheckboxes as $imageCheckbox) { + $imageCheckbox->click(); + } + + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->click($deleteSelectedButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($modalAcceptButton, 10); + $magentoWebDriver->click($modalAcceptButton); + $magentoWebDriver->waitForPageLoad(60); + $magentoWebDriver->waitForElementVisible($successMessageContainer, 10); + $magentoWebDriver->see($successMessage, $successMessageContainer); + + $rows = $webDriver->findElements(WebDriverBy::cssSelector($emptyRow)); + } + } catch (\Exception $e) { + $this->fail($e->getMessage()); + } + } +} diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml index 07f2dc23530e1..9018ccb4ddd69 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml @@ -13,5 +13,6 @@ <element name="cancelMassActionMode" type="button" selector="#cancel_massaction"/> <element name="deleteImages" type="button" selector="#delete_massaction"/> <element name="deleteSelected" type="button" selector="#delete_selected_massaction"/> + <element name="massActionCheckboxAll" type="checkbox" selector="[data-id='media-gallery-masonry-grid'] .mediagallery-massaction-checkbox input[type='checkbox']"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryGridSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryGridSection.xml index f35a32b6d3a37..08be2e61a9d14 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryGridSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryGridSection.xml @@ -8,7 +8,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminMediaGalleryGridSection"> - <element name="noDataMessage" type="text" selector="div.no-data-message-container"/> + <element name="noDataMessage" type="text" selector="[data-id='media-gallery-masonry-grid'] .no-data-message-container"/> <element name="nthImageInGrid" type="text" selector="div[class='masonry-image-column'][data-repeat-index='{{row}}'] img" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml new file mode 100644 index 0000000000000..42a936b6c0ebc --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminMediaGalleryMessagesSection"> + <element name="success" type="text" selector=".media-gallery-container ul.messages div.message.message-success span"/> + </section> +</sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyAssetFilterTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyAssetFilterTest.xml index 9a08f7cd0bb9c..847cc398d489d 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyAssetFilterTest.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyAssetFilterTest.xml @@ -7,16 +7,19 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminEnhancedMediaGalleryVerifyAssetFilterTest"> + <test name="AdminEnhancedMediaGalleryVerifyAssetFilterTest" deprecated="Use AdminEnhancedMediaGalleryVerifyFilterByAssetTest instead"> <annotations> <features value="MediaGallery"/> <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1292"/> - <title value="User sees entities where asset is used in"/> + <title value="DEPRECATED. User sees entities where asset is used in"/> <stories value="Story 58: User sees entities where asset is used in"/> <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951024"/> <description value="User sees entities where asset is used in"/> <severity value="CRITICAL"/> <group value="media_gallery_ui"/> + <skip> + <issueId value="DEPRECATED">Use AdminEnhancedMediaGalleryVerifyFilterByAssetTest instead</issueId> + </skip> </annotations> <before> <createData entity="SimpleSubCategory" stepKey="category"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml new file mode 100644 index 0000000000000..24259edbfe669 --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml @@ -0,0 +1,75 @@ +<?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="AdminEnhancedMediaGalleryVerifyFilterByAssetTest"> + <annotations> + <features value="MediaGallery"/> + <stories value="Story 58: User sees entities where asset is used in"/> + <title value="User sees entities where asset is used in"/> + <description value="User sees entities where asset is used in"/> + <severity value="CRITICAL"/> + <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951024"/> + <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1292"/> + <group value="media_gallery_ui"/> + </annotations> + + <before> + <createData entity="SimpleSubCategory" stepKey="category"/> + <actionGroup ref="EnabledWYSIWYGActionGroup" stepKey="enableWYSIWYG"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> + </before> + + <after> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <actionGroup ref="DisabledWYSIWYGActionGroup" stepKey="disableWYSIWYG"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> + + <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <actionGroup ref="GoToAdminCategoryPageByIdActionGroup" stepKey="openCategoryPage"> + <argument name="id" value="$category.id$"/> + </actionGroup> + <actionGroup ref="AdminOpenMediaGalleryTinyMce4ActionGroup" stepKey="openMediaGalleryFromWysiwyg"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadFirstIMage"> + <argument name="image" value="ImageUpload3"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadSecondImage"> + <argument name="image" value="ImageUpload_1"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickImageInGridActionGroup" stepKey="selectCategoryImageInGrid"> + <argument name="imageName" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickAddSelectedActionGroup" stepKey="clickAddSelectedContentImage"/> + <actionGroup ref="AdminMediaGalleryClickOkButtonTinyMce4ActionGroup" stepKey="clickOkButton"/> + <actionGroup ref="AdminSaveCategoryFormActionGroup" stepKey="saveCategory"/> + + <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultViewAgain"/> + <actionGroup ref="AdminEnhancedMediaGalleryCategoryGridExpandFilterActionGroup" stepKey="expandFilters"/> + <actionGroup ref="AdminEnhancedMediaGallerySelectUsedInFilterActionGroup" stepKey="setUsedInFilter"> + <argument name="filterName" value="Asset"/> + <argument name="optionName" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryCategoryGridApplyFiltersActionGroup" stepKey="applyFilters"/> + <actionGroup ref="AssertAdminCategoryGridPageNumberOfRecordsActionGroup" stepKey="assertOneRecordInGrid"> + <argument name="numberOfRecords" value="1 records found"/> + </actionGroup> + <actionGroup ref="AssertAdminCategoryGridPageImageColumnActionGroup" stepKey="assertCategoryGridPageImageColumn"/> + <actionGroup ref="AssertAdminCategoryGridPageDetailsActionGroup" stepKey="assertCategoryInGrid"> + <argument name="category" value="$category$"/> + </actionGroup> + <actionGroup ref="AssertAdminCategoryGridPageProductsInMenuEnabledColumnsActionGroup" stepKey="assertCategoryGridPageProductsInMenuEnabledColumns"/> + </test> +</tests> From 078919e3771fa662caa8c7d8378e5fd99b131b57 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 22 Oct 2020 17:05:35 +0300 Subject: [PATCH 29/59] MC-38589: [MFTF] AdminEnhancedMediaGalleryVerifyAssetFilterTest failed because of bad design --- .../Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml index 24259edbfe669..90ae7a5f10368 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml @@ -9,7 +9,7 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminEnhancedMediaGalleryVerifyFilterByAssetTest"> <annotations> - <features value="MediaGallery"/> + <features value="MediaGalleryUi"/> <stories value="Story 58: User sees entities where asset is used in"/> <title value="User sees entities where asset is used in"/> <description value="User sees entities where asset is used in"/> From 8baf70fd62ac58d95e33d1e00510504aa1a9abd4 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 22 Oct 2020 17:27:15 -0500 Subject: [PATCH 30/59] MC-37726: Price filter uses base currency for ranges --- .../LayeredNavigation/Builder/Price.php | 2 +- .../Model/Resolver/Aggregations.php | 25 ++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Price.php b/app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Price.php index 02b638edbdce8..1e2cc99663731 100644 --- a/app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Price.php +++ b/app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Price.php @@ -72,7 +72,7 @@ public function build(AggregationInterface $aggregation, ?int $storeId): array ); } - return [$result]; + return [self::PRICE_BUCKET => $result]; } /** diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php index 47a1d1f977f9b..7d10762d0f3b6 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php @@ -7,10 +7,12 @@ namespace Magento\CatalogGraphQl\Model\Resolver; +use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\LayerBuilder; +use Magento\Directory\Model\PriceCurrency; +use Magento\Framework\App\ObjectManager; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\LayerBuilder; use Magento\Store\Api\Data\StoreInterface; /** @@ -28,16 +30,24 @@ class Aggregations implements ResolverInterface */ private $layerBuilder; + /** + * @var PriceCurrency + */ + private $priceCurrency; + /** * @param \Magento\CatalogGraphQl\Model\Resolver\Layer\DataProvider\Filters $filtersDataProvider + * @param PriceCurrency $priceCurrency * @param LayerBuilder $layerBuilder */ public function __construct( \Magento\CatalogGraphQl\Model\Resolver\Layer\DataProvider\Filters $filtersDataProvider, - LayerBuilder $layerBuilder + LayerBuilder $layerBuilder, + PriceCurrency $priceCurrency = null ) { $this->filtersDataProvider = $filtersDataProvider; $this->layerBuilder = $layerBuilder; + $this->priceCurrency = $priceCurrency ?: ObjectManager::getInstance()->get(PriceCurrency::class); } /** @@ -60,7 +70,16 @@ public function resolve( /** @var StoreInterface $store */ $store = $context->getExtensionAttributes()->getStore(); $storeId = (int)$store->getId(); - return $this->layerBuilder->build($aggregations, $storeId); + $results = $this->layerBuilder->build($aggregations, $storeId); + if (isset($results['price_bucket'])) { + foreach ($results['price_bucket']['options'] as &$value) { + list($from, $to) = explode('-', $value['label']); + $newLabel = $this->priceCurrency->convertAndRound($from) . '-' . $this->priceCurrency->convertAndRound($to); + $value['label'] = $newLabel; + $value['value'] = str_replace('-', '_', $newLabel); + } + } + return $results; } else { return []; } From c53bb9b6cb544514354852a482e137d62bbbf932 Mon Sep 17 00:00:00 2001 From: Viktor Petryk <victor.petryk@transoftgroup.com> Date: Fri, 23 Oct 2020 12:27:36 +0300 Subject: [PATCH 31/59] MC-37213: [MFTF] AdminMediaGalleryCatalogUiUsedInProductFilterTest is flaky --- .../AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml index 32a07d6f6273f..a48256a4c2d29 100644 --- a/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml +++ b/app/code/Magento/MediaGalleryCatalogUi/Test/Mftf/Test/AdminMediaGalleryCatalogUiUsedInProductFilterOnTest.xml @@ -29,7 +29,7 @@ <magentoCLI command="config:set {{WysiwygDisabledByDefault.path}} {{WysiwygDisabledByDefault.value}}" stepKey="disableWYSIWYG"/> <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilters"/> <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetailsToAssertEmptyUsedIn"/> <actionGroup ref="AssertAdminEnhancedMediaGalleryUsedInSectionNotDisplayedActionGroup" stepKey="assertThereIsNoUsedInSection"/> <actionGroup ref="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup" stepKey="closeDetails"/> @@ -41,7 +41,7 @@ <actionGroup ref="AdminEnhancedMediaGalleryClickDeleteImagesButtonActionGroup" stepKey="clickDeleteSelectedButton"/> <actionGroup ref="AdminEnhancedMediaGalleryConfirmDeleteImagesActionGroup" stepKey="deleteImages"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView2"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersAfterDeleteImages"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> From 32be7bb1080b72d619262c1d575886450981c1b4 Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Fri, 23 Oct 2020 13:54:01 +0300 Subject: [PATCH 32/59] MC-33288: [2.4][MSI][MFTF] StorefrontLoggedInCustomerCreateOrderAllOptionQuantityConfigurableProductCustomStockTest fails because of bad design --- .../Model/ResourceModel/Product/Relation.php | 49 ++++++++++- .../ResourceModel/Product/RelationTest.php | 86 +++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/RelationTest.php diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php index c855fc5371b46..deba2b555d5cc 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php @@ -5,13 +5,37 @@ */ namespace Magento\Catalog\Model\ResourceModel\Product; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; +use Magento\Framework\EntityManager\MetadataPool; +use Magento\Catalog\Api\Data\ProductInterface; + /** * Catalog Product Relations Resource model * * @author Magento Core Team <core@magentocommerce.com> */ -class Relation extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb +class Relation extends AbstractDb { + /** + * @var MetadataPool + */ + private $metadataPool; + + /** + * @param Context $context + * @param null $connectionName + * @param MetadataPool $metadataPool + */ + public function __construct( + Context $context, + $connectionName = null, + MetadataPool $metadataPool + ) { + parent::__construct($context, $connectionName); + $this->metadataPool = $metadataPool; + } + /** * Initialize resource model and define main table * @@ -109,4 +133,27 @@ public function removeRelations($parentId, $childIds) } return $this; } + + /** + * Finds parent relations by given children ids. + * + * @param array $childrenIds Child products entity ids. + * @return array Parent products entity ids. + */ + public function getRelationsByChildren(array $childrenIds): array + { + $connection = $this->getConnection(); + $linkField = $this->metadataPool->getMetadata(ProductInterface::class) + ->getLinkField(); + $select = $connection->select() + ->from( + ['cpe' => $this->getTable('catalog_product_entity')], + 'entity_id' + )->join( + ['relation' => $this->getTable('catalog_product_relation')], + 'relation.parent_id = cpe.' . $linkField + )->where('child_id IN(?)', $childrenIds); + + return $connection->fetchCol($select); + } } diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/RelationTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/RelationTest.php new file mode 100644 index 0000000000000..e9fa6d5bf96b7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/RelationTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ConfigurableProduct\Model\ResourceModel\Product; + +use Magento\Catalog\Model\ResourceModel\Product\Relation; +use Magento\Framework\ObjectManagerInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * Tests Catalog Product Relation resource model. + * + * @see Relation + */ +class RelationTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var Relation + */ + private $model; + + /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(Relation::class); + $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class); + $this->searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + } + + /** + * Tests that getRelationsByChildren will return parent products entity ids of child products entity ids. + * + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_products.php + */ + public function testGetRelationsByChildren(): void + { + // Find configurable products options + $productOptionSkus = ['simple_10', 'simple_20', 'simple_30', 'simple_40']; + $searchCriteria = $this->searchCriteriaBuilder->addFilter('sku', $productOptionSkus, 'in') + ->create(); + $productOptions = $this->productRepository->getList($searchCriteria) + ->getItems(); + + $productOptionsIds = []; + + foreach ($productOptions as $productOption) { + $productOptionsIds[] = $productOption->getId(); + } + + // Find configurable products + $searchCriteria = $this->searchCriteriaBuilder->addFilter('sku', ['configurable', 'configurable_12345'], 'in') + ->create(); + $configurableProducts = $this->productRepository->getList($searchCriteria) + ->getItems(); + + // Assert there are configurable products ids in result of getRelationsByChildren method. + $result = $this->model->getRelationsByChildren($productOptionsIds); + + foreach ($configurableProducts as $configurableProduct) { + $this->assertContains($configurableProduct->getId(), $result); + } + } +} From 51b24f430911f2dfacb47cd77b37c8102c34c614 Mon Sep 17 00:00:00 2001 From: eduard13 <e.chitoraga@atwix.com> Date: Fri, 23 Oct 2020 16:05:16 +0300 Subject: [PATCH 33/59] Excluding the disabled parent category from the category breadcrumbs --- .../Category/DataProvider/Breadcrumbs.php | 2 + .../Magento/GraphQl/Catalog/CategoryTest.php | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/DataProvider/Breadcrumbs.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/DataProvider/Breadcrumbs.php index 863e621bd8df3..dcd6f816088dd 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/DataProvider/Breadcrumbs.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/DataProvider/Breadcrumbs.php @@ -7,6 +7,7 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Category\DataProvider; +use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; /** @@ -46,6 +47,7 @@ public function getData(string $categoryPath): array $collection = $this->collectionFactory->create(); $collection->addAttributeToSelect(['name', 'url_key', 'url_path']); $collection->addAttributeToFilter('entity_id', $parentCategoryIds); + $collection->addAttributeToFilter(CategoryInterface::KEY_IS_ACTIVE, 1); foreach ($collection as $category) { $breadcrumbsData[] = [ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php index f086a2211b51d..d31a0aa88efc1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoryTest.php @@ -660,6 +660,45 @@ public function testCategoryImage(?string $imagePrefix) $this->assertEquals($expectedImageUrl, $childCategory['image']); } + /** + * Testing breadcrumbs that shouldn't include disabled parent categories + * + * @magentoApiDataFixture Magento/Catalog/_files/categories.php + */ + public function testBreadCrumbsWithDisabledParentCategory() + { + $parentCategoryId = 4; + $childCategoryId = 5; + $category = $this->categoryRepository->get($parentCategoryId); + $category->setIsActive(false); + $this->categoryRepository->save($category); + + $query = <<<QUERY +{ + category(id: {$childCategoryId}) { + name + breadcrumbs { + category_id + category_name + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + $expectedResponse = [ + 'category' => [ + 'name' => 'Category 1.1.1', + 'breadcrumbs' => [ + [ + 'category_id' => 3, + 'category_name' => "Category 1", + ] + ] + ] + ]; + $this->assertEquals($expectedResponse, $response); + } + /** * @return array */ From 97c350bbbb60aee37293a6e5afd8306c9ce4bf6e Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Fri, 23 Oct 2020 15:41:06 -0500 Subject: [PATCH 34/59] MC-37726: Price filter uses base currency for ranges --- .../Model/Resolver/Aggregations.php | 4 +- .../Catalog/ProductSearchAggregationsTest.php | 133 +++++++++++++++--- 2 files changed, 114 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php index 7d10762d0f3b6..cddb95d5ba765 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php @@ -74,7 +74,9 @@ public function resolve( if (isset($results['price_bucket'])) { foreach ($results['price_bucket']['options'] as &$value) { list($from, $to) = explode('-', $value['label']); - $newLabel = $this->priceCurrency->convertAndRound($from) . '-' . $this->priceCurrency->convertAndRound($to); + $newLabel = $this->priceCurrency->convertAndRound($from) + . '-' + . $this->priceCurrency->convertAndRound($to); $value['label'] = $newLabel; $value['value'] = str_replace('-', '_', $newLabel); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php index 9dbd902f1714e..075388b0f023c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php @@ -7,6 +7,11 @@ namespace Magento\GraphQl\Catalog; +use Magento\Config\App\Config\Type\System; +use Magento\Config\Model\ResourceModel\Config; +use Magento\Directory\Model\Currency; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\Store; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -22,28 +27,9 @@ public function testAggregationBooleanAttribute() . 'MC-36768: Custom attribute not appears in elasticsearch' ); - $skus= '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"'; - $query = <<<QUERY -{ - products(filter: {sku: {in: [{$skus}]}}){ - items{ - id - sku - name - } - aggregations{ - label - attribute_code - count - options{ - label - value - count - } - } - } -} -QUERY; + $query = $this->getGraphQlQuery( + '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"' + ); $result = $this->graphQlQuery($query); @@ -69,4 +55,107 @@ function ($a) { $this->assertCount(2, $booleanAggregation['options']); $this->assertContainsEquals(['label' => '0', 'value'=> '0', 'count' => '2'], $booleanAggregation['options']); } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_for_search.php + */ + public function testAggregationPriceRanges() + { + $query = $this->getGraphQlQuery( + '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"' + ); + $result = $this->graphQlQuery($query); + + $this->assertArrayNotHasKey('errors', $result); + $this->assertArrayHasKey('aggregations', $result['products']); + + $priceAggregation = array_filter( + $result['products']['aggregations'], + function ($a) { + return $a['attribute_code'] == 'price'; + } + ); + $this->assertNotEmpty($priceAggregation); + $priceAggregation = reset($priceAggregation); + $this->assertEquals('Price', $priceAggregation['label']); + $this->assertEquals(4, $priceAggregation['count']); + $expectedOptions = [ + ['label' => '10-20', 'value'=> '10_20', 'count' => '2'], + ['label' => '20-30', 'value'=> '20_30', 'count' => '1'], + ['label' => '30-40', 'value'=> '30_40', 'count' => '1'], + ['label' => '40-50', 'value'=> '40_50', 'count' => '1'] + ]; + $this->assertEquals($expectedOptions, $priceAggregation['options']); + } + + /** + * @magentoApiDataFixture Magento/Store/_files/second_store_with_second_currency.php + * @magentoApiDataFixture Magento/Catalog/_files/products_for_search.php + */ + public function testAggregationPriceRangesWithCurrencyHeader() + { + // add USD as allowed (not default) currency + $objectManager = Bootstrap::getObjectManager(); + /* @var Store $store */ + $store = $objectManager->create(Store::class); + $store->load('fixture_second_store'); + /** @var Config $configResource */ + $configResource = $objectManager->get(Config::class); + $configResource->saveConfig( + Currency::XML_PATH_CURRENCY_ALLOW, + 'USD', + ScopeInterface::SCOPE_STORES, + $store->getId() + ); + // Configuration cache clean is required to reload currency setting + /** @var System $config */ + $config = $objectManager->get(System::class); + $config->clean(); + + $headerMap['Store'] = 'fixture_second_store'; + $headerMap['Content-Currency'] = 'USD'; + $query = $this->getGraphQlQuery( + '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"' + ); + $result = $this->graphQlQuery($query, [], '', $headerMap); + $this->assertArrayNotHasKey('errors', $result); + $this->assertArrayHasKey('aggregations', $result['products']); + $priceAggregation = array_filter( + $result['products']['aggregations'], + function ($a) { + return $a['attribute_code'] == 'price'; + } + ); + $this->assertNotEmpty($priceAggregation); + $priceAggregation = reset($priceAggregation); + $this->assertEquals('Price', $priceAggregation['label']); + $this->assertEquals(4, $priceAggregation['count']); + $expectedOptions = [ + ['label' => '10-20', 'value'=> '10_20', 'count' => '2'], + ['label' => '20-30', 'value'=> '20_30', 'count' => '1'], + ['label' => '30-40', 'value'=> '30_40', 'count' => '1'], + ['label' => '40-50', 'value'=> '40_50', 'count' => '1'] + ]; + $this->assertEquals($expectedOptions, $priceAggregation['options']); + } + + private function getGraphQlQuery(string $skus) + { + return <<<QUERY +{ + products(filter: {sku: {in: [{$skus}]}}){ + aggregations{ + label + attribute_code + count + options{ + label + value + count + } + } + } +} +QUERY; + } } From 3009cdc6772ec1e8b0fae0eaad37865fb88c70dc Mon Sep 17 00:00:00 2001 From: Andrii Beziazychnyi <a.beziazychnyi@atwix.com> Date: Sat, 24 Oct 2020 02:16:44 +0300 Subject: [PATCH 35/59] M2CE-30469: [GRAPHQL] Made the attribute `destination_cart_id` for mergeCarts mutation not required. --- .../Model/Resolver/MergeCarts.php | 81 +++++++++++++++---- .../Magento/QuoteGraphQl/etc/schema.graphqls | 2 +- .../GraphQl/Quote/Customer/MergeCartsTest.php | 3 - 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php index d77d19df55603..50682413aea1e 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php @@ -7,17 +7,23 @@ namespace Magento\QuoteGraphQl\Model\Resolver; +use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; -use Magento\Quote\Api\CartRepositoryInterface; use Magento\GraphQl\Model\Query\ContextInterface; -use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Cart\CustomerCartResolver; +use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; +use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; /** * Merge Carts Resolver + * + * @SuppressWarnings(PHPMD.LongVariable) */ class MergeCarts implements ResolverInterface { @@ -31,44 +37,87 @@ class MergeCarts implements ResolverInterface */ private $cartRepository; + /** + * @var CustomerCartResolver + */ + private $customerCartResolver; + + /** + * @var QuoteIdToMaskedQuoteIdInterface + */ + private $quoteIdToMaskedQuoteId; + /** * @param GetCartForUser $getCartForUser * @param CartRepositoryInterface $cartRepository + * @param CustomerCartResolver $customerCartResolver + * @param QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId */ public function __construct( GetCartForUser $getCartForUser, - CartRepositoryInterface $cartRepository + CartRepositoryInterface $cartRepository, + CustomerCartResolver $customerCartResolver, + QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId ) { $this->getCartForUser = $getCartForUser; $this->cartRepository = $cartRepository; + $this->customerCartResolver = $customerCartResolver; + $this->quoteIdToMaskedQuoteId = $quoteIdToMaskedQuoteId; } /** * @inheritdoc */ - public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) - { + public function resolve( + Field $field, + $context, + ResolveInfo $info, + array $value = null, + array $args = null + ) { if (empty($args['source_cart_id'])) { - throw new GraphQlInputException(__('Required parameter "source_cart_id" is missing')); - } - - if (empty($args['destination_cart_id'])) { - throw new GraphQlInputException(__('Required parameter "destination_cart_id" is missing')); + throw new GraphQlInputException(__( + 'Required parameter "source_cart_id" is missing' + )); } /** @var ContextInterface $context */ if (false === $context->getExtensionAttributes()->getIsCustomer()) { - throw new GraphQlAuthorizationException(__('The current customer isn\'t authorized.')); + throw new GraphQlAuthorizationException(__( + 'The current customer isn\'t authorized.' + )); + } + $currentUserId = $context->getUserId(); + + if (empty($args['destination_cart_id'])) { + try { + $cart = $this->customerCartResolver->resolve($currentUserId); + } catch (CouldNotSaveException $exception) { + throw new GraphQlNoSuchEntityException( + __('Could not create empty cart for customer'), + $exception + ); + } + $customerMaskedCartId = $this->quoteIdToMaskedQuoteId->execute( + (int) $cart->getId() + ); } $guestMaskedCartId = $args['source_cart_id']; - $customerMaskedCartId = $args['destination_cart_id']; + $customerMaskedCartId = $customerMaskedCartId ?? $args['destination_cart_id']; - $currentUserId = $context->getUserId(); $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); // passing customerId as null enforces source cart should always be a guestcart - $guestCart = $this->getCartForUser->execute($guestMaskedCartId, null, $storeId); - $customerCart = $this->getCartForUser->execute($customerMaskedCartId, $currentUserId, $storeId); + $guestCart = $this->getCartForUser->execute( + $guestMaskedCartId, + null, + $storeId + ); + $customerCart = $this->getCartForUser->execute( + $customerMaskedCartId, + $currentUserId, + $storeId + ); $customerCart->merge($guestCart); $guestCart->setIsActive(false); $this->cartRepository->save($customerCart); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 4e0e7ce5732be..cc9d1803b3e31 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -20,7 +20,7 @@ type Mutation { setPaymentMethodOnCart(input: SetPaymentMethodOnCartInput): SetPaymentMethodOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetPaymentMethodOnCart") setGuestEmailOnCart(input: SetGuestEmailOnCartInput): SetGuestEmailOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetGuestEmailOnCart") setPaymentMethodAndPlaceOrder(input: SetPaymentMethodAndPlaceOrderInput): PlaceOrderOutput @deprecated(reason: "Should use setPaymentMethodOnCart and placeOrder mutations in single request.") @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetPaymentAndPlaceOrder") - mergeCarts(source_cart_id: String!, destination_cart_id: String!): Cart! @doc(description:"Merges the source cart into the destination cart") @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\MergeCarts") + mergeCarts(source_cart_id: String!, destination_cart_id: String): Cart! @doc(description:"Merges the source cart into the destination cart") @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\MergeCarts") placeOrder(input: PlaceOrderInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\PlaceOrder") addProductsToCart(cartId: String!, cartItems: [CartItemInput!]!): AddProductsToCartOutput @doc(description:"Add any type of product to the cart") @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddProductsToCart") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php index 65e91bf193020..b33d9982b8187 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php @@ -192,9 +192,6 @@ public function testMergeCartsWithEmptySourceCartId() */ public function testMergeCartsWithEmptyDestinationCartId() { - $this->expectException(\Exception::class); - $this->expectExceptionMessage('Required parameter "destination_cart_id" is missing'); - $guestQuote = $this->quoteFactory->create(); $this->quoteResource->load( $guestQuote, From d4e5894ae29b8088c8cc6db59f332bfc70dd9a4a Mon Sep 17 00:00:00 2001 From: Andrii Beziazychnyi <a.beziazychnyi@atwix.com> Date: Sun, 25 Oct 2020 22:28:53 +0200 Subject: [PATCH 36/59] M2CE-30469: The tests and logic fixes --- .../Model/Resolver/MergeCarts.php | 8 +- .../GraphQl/Quote/Customer/MergeCartsTest.php | 76 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php index 50682413aea1e..d53ab597eaba4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php @@ -89,7 +89,7 @@ public function resolve( } $currentUserId = $context->getUserId(); - if (empty($args['destination_cart_id'])) { + if (!isset($args['destination_cart_id'])) { try { $cart = $this->customerCartResolver->resolve($currentUserId); } catch (CouldNotSaveException $exception) { @@ -101,6 +101,12 @@ public function resolve( $customerMaskedCartId = $this->quoteIdToMaskedQuoteId->execute( (int) $cart->getId() ); + } else { + if (empty($args['destination_cart_id'])) { + throw new GraphQlInputException(__( + 'The parameter "destination_cart_id" cannot be empty' + )); + } } $guestMaskedCartId = $args['source_cart_id']; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php index b33d9982b8187..4f50b9df3098a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/MergeCartsTest.php @@ -192,6 +192,9 @@ public function testMergeCartsWithEmptySourceCartId() */ public function testMergeCartsWithEmptyDestinationCartId() { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('The parameter "destination_cart_id" cannot be empty'); + $guestQuote = $this->quoteFactory->create(); $this->quoteResource->load( $guestQuote, @@ -206,6 +209,54 @@ public function testMergeCartsWithEmptyDestinationCartId() $this->graphQlMutation($query, [], '', $this->getHeaderMap()); } + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testMergeCartsWithoutDestinationCartId() + { + $guestQuote = $this->quoteFactory->create(); + $this->quoteResource->load( + $guestQuote, + 'test_order_with_virtual_product_without_address', + 'reserved_order_id' + ); + $guestQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$guestQuote->getId()); + $query = $this->getCartMergeMutationWithoutDestinationCartId( + $guestQuoteMaskedId + ); + $mergeResponse = $this->graphQlMutation($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('mergeCarts', $mergeResponse); + $cartResponse = $mergeResponse['mergeCarts']; + self::assertArrayHasKey('items', $cartResponse); + self::assertCount(2, $cartResponse['items']); + + $customerQuote = $this->quoteFactory->create(); + $this->quoteResource->load($customerQuote, 'test_quote', 'reserved_order_id'); + $customerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$customerQuote->getId()); + + $cartResponse = $this->graphQlMutation( + $this->getCartQuery($customerQuoteMaskedId), + [], + '', + $this->getHeaderMap() + ); + + self::assertArrayHasKey('cart', $cartResponse); + self::assertArrayHasKey('items', $cartResponse['cart']); + self::assertCount(2, $cartResponse['cart']['items']); + $item1 = $cartResponse['cart']['items'][0]; + self::assertArrayHasKey('quantity', $item1); + self::assertEquals(2, $item1['quantity']); + $item2 = $cartResponse['cart']['items'][1]; + self::assertArrayHasKey('quantity', $item2); + self::assertEquals(1, $item2['quantity']); + } + /** * Add simple product to cart * @@ -253,6 +304,31 @@ private function getCartMergeMutation(string $guestQuoteMaskedId, string $custom QUERY; } + /** + * Create the mergeCart mutation + * + * @param string $guestQuoteMaskedId + * @return string + */ + private function getCartMergeMutationWithoutDestinationCartId( + string $guestQuoteMaskedId + ): string { + return <<<QUERY +mutation { + mergeCarts( + source_cart_id: "{$guestQuoteMaskedId}" + ){ + items { + quantity + product { + sku + } + } + } +} +QUERY; + } + /** * Get cart query * From 80c3184e9655f3a003119b30dbc744839dad5c63 Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Mon, 26 Oct 2020 11:06:56 +0200 Subject: [PATCH 37/59] MC-38488: [MFTF] AdminMediaGalleryAssertUsedInLinkBlocksGridTest failed because of bad design --- ...eryAssertImageUsedInLinkBlocksGridTest.xml | 63 ++++++++------- ...ediaGalleryDeletedAllImagesActionGroup.xml | 30 ++++++++ .../Test/Mftf/Helper/MediaGalleryUiHelper.php | 77 +++++++++++++++++++ ...nhancedMediaGalleryImageActionsSection.xml | 2 +- ...nEnhancedMediaGalleryMassActionSection.xml | 1 + .../AdminMediaGalleryMessagesSection.xml | 13 ++++ .../web/js/grid/filters/elements/ui-select.js | 4 +- 7 files changed, 155 insertions(+), 35 deletions(-) create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml index c25e55cd30461..63f6a483665c9 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml @@ -9,29 +9,44 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest"> <annotations> - <features value="AdminMediaGalleryUsedInBlocksFilter"/> - <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1168"/> - <title value="Used in blocks link"/> + <features value="MediaGalleryCmsUi"/> <stories value="Story 58: User sees entities where asset is used in" /> - <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951848"/> + <title value="Used in blocks link"/> <description value="User filters assets used in blocks"/> <severity value="CRITICAL"/> + <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951848"/> + <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1168"/> <group value="media_gallery_ui"/> </annotations> <before> - <createData entity="_defaultBlock" stepKey="block" /> - <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> + <createData entity="_defaultBlock" stepKey="createBlock" /> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> </before> <after> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> - <actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> - <actionGroup ref="CliCacheFlushActionGroup" stepKey="flushCacheAfterTest"> - <argument name="tags" value="block_html"/> + <deleteData createDataKey="createBlock" stepKey="deleteBlock"/> + + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultViewAgain"/> + <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolderAgain"> + <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> + </actionGroup> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetailsToVerifyEmptyUsedIn"/> + <actionGroup ref="AssertAdminEnhancedMediaGalleryUsedInSectionNotDisplayedActionGroup" stepKey="assertThereIsNoUsedInSection"/> + <actionGroup ref="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup" stepKey="closeImageDetails"/> + + <actionGroup ref="AdminMediaGalleryFolderDeleteActionGroup" stepKey="deleteFolder"/> + <actionGroup ref="AdminMediaGalleryAssertFolderDoesNotExistActionGroup" stepKey="assertFolderWasDeleted"> + <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> + + <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImagesAfterTest"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> <actionGroup ref="NavigateToCreatedCMSBlockPageActionGroup" stepKey="navigateToCreatedCMSBlockPage"> - <argument name="CMSBlockPage" value="$$block$$"/> + <argument name="CMSBlockPage" value="$createBlock$"/> </actionGroup> <click selector="{{CmsWYSIWYGSection.InsertImageBtn}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForInitialPageLoad" /> @@ -39,10 +54,10 @@ <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> <actionGroup ref="AdminMediaGalleryOpenNewFolderFormActionGroup" stepKey="openNewFolderForm"/> <actionGroup ref="AdminMediaGalleryCreateNewFolderActionGroup" stepKey="createNewFolder"> - <argument name="name" value="blockImage"/> + <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> <actionGroup ref="AdminMediaGalleryAssertFolderNameActionGroup" stepKey="assertNewFolderCreated"> - <argument name="name" value="blockImage"/> + <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> <waitForPageLoad stepKey="waitForGridToLoadAfterNewFolderCreated"/> <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadImage"> @@ -57,34 +72,16 @@ <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openStandaloneMediaGallery"/> <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolder"> - <argument name="name" value="blockImage"/> + <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetails"/> <actionGroup ref="AdminEnhancedMediaGalleryClickEntityUsedInActionGroup" stepKey="clickUsedInBlocks"> <argument name="entityName" value="Blocks"/> </actionGroup> - <wait time="5" stepKey="waitForAssertLoads"/> - <reloadPage stepKey="reloadBlocksGridPage"/> - <waitForPageLoad stepKey="waitForBlocksGridPageLoad"/> + <actionGroup ref="AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup" stepKey="assertFilterApplied"> <argument name="filterPlaceholder" value="{{ImageMetadata.title}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilterInBlocksGrid"/> - - <deleteData createDataKey="block" stepKey="deleteBlock"/> - - <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultViewAgain"/> - <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolderAgain"> - <argument name="name" value="blockImage"/> - </actionGroup> - <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetailsToVerifyEmptyUsedIn"/> - <actionGroup ref="AssertAdminEnhancedMediaGalleryUsedInSectionNotDisplayedActionGroup" stepKey="assertThereIsNoUsedInSection"/> - <actionGroup ref="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup" stepKey="closeImageDetails"/> - - <actionGroup ref="AdminMediaGalleryFolderDeleteActionGroup" stepKey="deleteFolder"/> - <actionGroup ref="AdminMediaGalleryAssertFolderDoesNotExistActionGroup" stepKey="assertFolderWasDeleted"> - <argument name="name" value="blockImage"/> - </actionGroup> </test> </tests> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml new file mode 100644 index 0000000000000..f77521879c8ea --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup"> + <annotations> + <description>Open Media Gallery page and delete all images</description> + </annotations> + + <amOnPage url="{{AdminStandaloneMediaGalleryPage.url}}" stepKey="openMediaGalleryPage"/> + <!-- It sometimes is loading too long for default 10s --> + <waitForPageLoad time="60" stepKey="waitForPageFullyLoaded"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingFilters"/> + <helper class="\Magento\MediaGalleryUi\Test\Mftf\Helper\MediaGalleryUiHelper" method="deleteAllImagesUsingMassAction" stepKey="deleteAllImagesUsingMassAction"> + <argument name="emptyRow">{{AdminMediaGalleryGridSection.noDataMessage}}</argument> + <argument name="deleteImagesButton">{{AdminEnhancedMediaGalleryMassActionSection.deleteImages}}</argument> + <argument name="checkImage">{{AdminEnhancedMediaGalleryMassActionSection.massActionCheckboxAll}}</argument> + <argument name="deleteSelectedButton">{{AdminEnhancedMediaGalleryMassActionSection.deleteSelected}}</argument> + <argument name="modalAcceptButton">{{AdminEnhancedMediaGalleryDeleteModalSection.confirmDelete}}</argument> + <argument name="successMessageContainer">{{AdminMediaGalleryMessagesSection.success}}</argument> + <argument name="successMessage">been successfully deleted</argument> + </helper> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php b/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php new file mode 100644 index 0000000000000..4059a8460bb51 --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MediaGalleryUi\Test\Mftf\Helper; + +use Facebook\WebDriver\Remote\RemoteWebDriver as FacebookWebDriver; +use Facebook\WebDriver\Remote\RemoteWebElement; +use Facebook\WebDriver\WebDriverBy; +use Magento\FunctionalTestingFramework\Helper\Helper; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; + +/** + * Class for MFTF helpers for MediaGalleryUi module. + */ +class MediaGalleryUiHelper extends Helper +{ + /** + * Delete all images using mass action. + * + * @param string $emptyRow + * @param string $deleteImagesButton + * @param string $checkImage + * @param string $deleteSelectedButton + * @param string $modalAcceptButton + * @param string $successMessageContainer + * @param string $successMessage + * + * @return void + */ + public function deleteAllImagesUsingMassAction( + string $emptyRow, + string $deleteImagesButton, + string $checkImage, + string $deleteSelectedButton, + string $modalAcceptButton, + string $successMessageContainer, + string $successMessage + ): void { + try { + /** @var MagentoWebDriver $webDriver */ + $magentoWebDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + /** @var FacebookWebDriver $webDriver */ + $webDriver = $magentoWebDriver->webDriver; + $rows = $webDriver->findElements(WebDriverBy::cssSelector($emptyRow)); + while (empty($rows)) { + $magentoWebDriver->click($deleteImagesButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($deleteSelectedButton, 10); + + // Check all images + /** @var RemoteWebElement[] $images */ + $imagesCheckboxes = $webDriver->findElements(WebDriverBy::cssSelector($checkImage)); + /** @var RemoteWebElement $image */ + foreach ($imagesCheckboxes as $imageCheckbox) { + $imageCheckbox->click(); + } + + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->click($deleteSelectedButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($modalAcceptButton, 10); + $magentoWebDriver->click($modalAcceptButton); + $magentoWebDriver->waitForPageLoad(60); + $magentoWebDriver->waitForElementVisible($successMessageContainer, 10); + $magentoWebDriver->see($successMessage, $successMessageContainer); + + $rows = $webDriver->findElements(WebDriverBy::cssSelector($emptyRow)); + } + } catch (\Exception $e) { + $this->fail($e->getMessage()); + } + } +} diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml index a8e9feaa2d623..bfb92f0cd8ee7 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml @@ -10,7 +10,7 @@ <section name="AdminEnhancedMediaGalleryImageActionsSection"> <element name="openContextMenu" type="button" selector=".three-dots"/> <element name="contextMenuItem" type="block" selector="//div[@class='media-gallery-image']//ul[@class='action-menu _active']//li//a[@class='action-menu-item']"/> - <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[@class='action-menu-item' and contains(text(), 'View Details')]" timeout="30" /> + <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[text()='View Details']" timeout="30" /> <element name="delete" type="button" selector="[data-ui-id='action-delete']"/> <element name="edit" type="button" selector="[data-ui-id='action-edit']"/> <element name="imageInGrid" type="button" selector="//li[@data-ui-id='title'and text()='{{imageTitle}}']/parent::*/parent::*/parent::div//img[@class='media-gallery-image-column']" parameterized="true"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml index 07f2dc23530e1..9018ccb4ddd69 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml @@ -13,5 +13,6 @@ <element name="cancelMassActionMode" type="button" selector="#cancel_massaction"/> <element name="deleteImages" type="button" selector="#delete_massaction"/> <element name="deleteSelected" type="button" selector="#delete_selected_massaction"/> + <element name="massActionCheckboxAll" type="checkbox" selector="[data-id='media-gallery-masonry-grid'] .mediagallery-massaction-checkbox input[type='checkbox']"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml new file mode 100644 index 0000000000000..42a936b6c0ebc --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminMediaGalleryMessagesSection"> + <element name="success" type="text" selector=".media-gallery-container ul.messages div.message.message-success span"/> + </section> +</sections> diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js index a913f3fa4a042..cddcc7d49ffe8 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/elements/ui-select.js @@ -18,13 +18,15 @@ define([ loadedOption: [], validationLoading: true, imports: { + applied: '${ $.filterChipsProvider }:applied', activeIndex: '${ $.bookmarkProvider }:activeIndex' }, modules: { filterChips: '${ $.filterChipsProvider }' }, listens: { - activeIndex: 'validateInitialValue' + activeIndex: 'validateInitialValue', + applied: 'validateInitialValue' } }, From 0e9238ea655adbc361d5d9077bdd7efea28b8c93 Mon Sep 17 00:00:00 2001 From: SmVladyslav <vlatame.tsg@gmail.com> Date: Mon, 26 Oct 2020 12:18:32 +0200 Subject: [PATCH 38/59] MC-37120: Shopping cart is empty after adding simple product if another product was removed from Multiple Addresses checkout before --- .../Model/DisableMultishipping.php | 38 ++++++ .../Observer/DisableMultishippingObserver.php | 46 +++++++ .../Plugin/DisableMultishippingMode.php | 25 ++-- .../Unit/Model/DisableMultishippingTest.php | 116 ++++++++++++++++++ .../Plugin/DisableMultishippingModeTest.php | 90 +++++++++----- .../Multishipping/etc/frontend/events.xml | 12 ++ .../DisableMultishippingObserverTest.php | 87 +++++++++++++ .../Plugin/DisableMultishippingModeTest.php | 70 +++++++++++ 8 files changed, 442 insertions(+), 42 deletions(-) create mode 100644 app/code/Magento/Multishipping/Model/DisableMultishipping.php create mode 100644 app/code/Magento/Multishipping/Observer/DisableMultishippingObserver.php create mode 100644 app/code/Magento/Multishipping/Test/Unit/Model/DisableMultishippingTest.php create mode 100644 app/code/Magento/Multishipping/etc/frontend/events.xml create mode 100644 dev/tests/integration/testsuite/Magento/Multishipping/Observer/DisableMultishippingObserverTest.php create mode 100644 dev/tests/integration/testsuite/Magento/Multishipping/Plugin/DisableMultishippingModeTest.php diff --git a/app/code/Magento/Multishipping/Model/DisableMultishipping.php b/app/code/Magento/Multishipping/Model/DisableMultishipping.php new file mode 100644 index 0000000000000..a871cee715538 --- /dev/null +++ b/app/code/Magento/Multishipping/Model/DisableMultishipping.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Multishipping\Model; + +use Magento\Quote\Api\Data\CartInterface; + +/** + * Turn Off Multishipping mode if enabled. + */ +class DisableMultishipping +{ + /** + * Disable Multishipping mode for provided Quote and return TRUE if it was changed. + * + * @param CartInterface $quote + * @return bool + */ + public function execute(CartInterface $quote): bool + { + $modeChanged = false; + if ($quote->getIsMultiShipping()) { + $quote->setIsMultiShipping(0); + $extensionAttributes = $quote->getExtensionAttributes(); + if ($extensionAttributes && $extensionAttributes->getShippingAssignments()) { + $extensionAttributes->setShippingAssignments([]); + } + + $modeChanged = true; + } + + return $modeChanged; + } +} diff --git a/app/code/Magento/Multishipping/Observer/DisableMultishippingObserver.php b/app/code/Magento/Multishipping/Observer/DisableMultishippingObserver.php new file mode 100644 index 0000000000000..a72bce87965a4 --- /dev/null +++ b/app/code/Magento/Multishipping/Observer/DisableMultishippingObserver.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Multishipping\Observer; + +use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Event\Observer as EventObserver; +use Magento\Multishipping\Model\DisableMultishipping; +use Magento\Quote\Api\Data\CartInterface; + +/** + * Observer for disabling Multishipping mode. + */ +class DisableMultishippingObserver implements ObserverInterface +{ + /** + * @var DisableMultishipping + */ + private $disableMultishipping; + + /** + * @param DisableMultishipping $disableMultishipping + */ + public function __construct( + DisableMultishipping $disableMultishipping + ) { + $this->disableMultishipping = $disableMultishipping; + } + + /** + * Disable Multishipping mode before saving Quote. + * + * @param EventObserver $observer + * @return void + */ + public function execute(EventObserver $observer): void + { + /** @var CartInterface $quote */ + $quote = $observer->getEvent()->getCart()->getQuote(); + $this->disableMultishipping->execute($quote); + } +} diff --git a/app/code/Magento/Multishipping/Plugin/DisableMultishippingMode.php b/app/code/Magento/Multishipping/Plugin/DisableMultishippingMode.php index fff2346d76240..f4e6928173f60 100644 --- a/app/code/Magento/Multishipping/Plugin/DisableMultishippingMode.php +++ b/app/code/Magento/Multishipping/Plugin/DisableMultishippingMode.php @@ -9,6 +9,7 @@ use Magento\Checkout\Model\Cart; use Magento\Framework\App\Action\Action; +use Magento\Multishipping\Model\DisableMultishipping; /** * Turns Off Multishipping mode for Quote. @@ -20,13 +21,21 @@ class DisableMultishippingMode */ private $cart; + /** + * @var DisableMultishipping + */ + private $disableMultishipping; + /** * @param Cart $cart + * @param DisableMultishipping $disableMultishipping */ public function __construct( - Cart $cart + Cart $cart, + DisableMultishipping $disableMultishipping ) { $this->cart = $cart; + $this->disableMultishipping = $disableMultishipping; } /** @@ -36,16 +45,16 @@ public function __construct( * @return void * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function beforeExecute(Action $subject) + public function beforeExecute(Action $subject): void { $quote = $this->cart->getQuote(); - if ($quote->getIsMultiShipping()) { - $quote->setIsMultiShipping(0); - $extensionAttributes = $quote->getExtensionAttributes(); - if ($extensionAttributes && $extensionAttributes->getShippingAssignments()) { - $extensionAttributes->setShippingAssignments([]); - } + $modChanged = $this->disableMultishipping->execute($quote); + if ($modChanged) { + $totalsCollectedBefore = $quote->getTotalsCollectedFlag(); $this->cart->saveQuote(); + if (!$totalsCollectedBefore) { + $quote->setTotalsCollectedFlag(false); + } } } } diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/DisableMultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/DisableMultishippingTest.php new file mode 100644 index 0000000000000..9882f8d1441aa --- /dev/null +++ b/app/code/Magento/Multishipping/Test/Unit/Model/DisableMultishippingTest.php @@ -0,0 +1,116 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Multishipping\Test\Unit\Model; + +use Magento\Multishipping\Model\DisableMultishipping; +use Magento\Quote\Api\Data\CartExtensionInterface; +use Magento\Quote\Api\Data\CartInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * 'Disable Multishipping' model unit tests. + */ +class DisableMultishippingTest extends TestCase +{ + /** + * @var CartInterface|MockObject + */ + private $quoteMock; + + /** + * @var DisableMultishipping + */ + private $disableMultishippingModel; + + /** + * @inheritdoc + */ + protected function setUp(): void + { + $this->quoteMock = $this->getMockBuilder(CartInterface::class) + ->addMethods(['getIsMultiShipping', 'setIsMultiShipping']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->disableMultishippingModel = new DisableMultishipping(); + } + + /** + * Test 'execute' method if 'MultiShipping' mode is enabled. + * + * @param bool $hasShippingAssignments + * @return void + * @dataProvider executeWithMultishippingModeEnabledDataProvider + */ + public function testExecuteWithMultishippingModeEnabled(bool $hasShippingAssignments): void + { + $shippingAssignments = $hasShippingAssignments ? ['example_shipping_assigment'] : null; + + $this->quoteMock->expects($this->once()) + ->method('getIsMultiShipping') + ->willReturn(true); + + $this->quoteMock->expects($this->once()) + ->method('setIsMultiShipping') + ->with(0); + + /** @var CartExtensionInterface|MockObject $extensionAttributesMock */ + $extensionAttributesMock = $this->getMockBuilder(CartExtensionInterface::class) + ->addMethods(['getShippingAssignments', 'setShippingAssignments']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $extensionAttributesMock->expects($this->once()) + ->method('getShippingAssignments') + ->willReturn($shippingAssignments); + + $extensionAttributesMock->expects($hasShippingAssignments ? $this->once() : $this->never()) + ->method('setShippingAssignments') + ->with([]) + ->willReturnSelf(); + + $this->quoteMock->expects($this->once()) + ->method('getExtensionAttributes') + ->willReturn($extensionAttributesMock); + + $this->assertTrue($this->disableMultishippingModel->execute($this->quoteMock)); + } + + /** + * DataProvider for testExecuteWithMultishippingModeEnabled(). + * + * @return array + */ + public function executeWithMultishippingModeEnabledDataProvider(): array + { + return [ + 'check_with_shipping_assignments' => [true], + 'check_without_shipping_assignments' => [false] + ]; + } + + /** + * Test 'execute' method if 'Multishipping' mode is disabled. + * + * @return void + */ + public function testExecuteWithMultishippingModeDisabled(): void + { + $this->quoteMock->expects($this->once()) + ->method('getIsMultiShipping') + ->willReturn(false); + + $this->quoteMock->expects($this->never()) + ->method('setIsMultiShipping'); + + $this->quoteMock->expects($this->never()) + ->method('getExtensionAttributes'); + + $this->assertFalse($this->disableMultishippingModel->execute($this->quoteMock)); + } +} diff --git a/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php b/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php index fb16bd251706c..64cbcbf147d48 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Plugin/DisableMultishippingModeTest.php @@ -10,10 +10,9 @@ use Magento\Checkout\Controller\Index\Index; use Magento\Checkout\Model\Cart; +use Magento\Multishipping\Model\DisableMultishipping as DisableMultishippingModel; use Magento\Multishipping\Plugin\DisableMultishippingMode; -use Magento\Quote\Api\Data\CartExtensionInterface; -use Magento\Quote\Api\Data\ShippingAssignmentInterface; -use Magento\Quote\Model\Quote; +use Magento\Quote\Api\Data\CartInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -23,15 +22,20 @@ class DisableMultishippingModeTest extends TestCase { /** - * @var MockObject + * @var Cart|MockObject */ private $cartMock; /** - * @var MockObject + * @var CartInterface|MockObject */ private $quoteMock; + /** + * @var DisableMultishippingModel|MockObject + */ + private $disableMultishippingMock; + /** * @var DisableMultishippingMode */ @@ -43,43 +47,40 @@ class DisableMultishippingModeTest extends TestCase protected function setUp(): void { $this->cartMock = $this->createMock(Cart::class); - $this->quoteMock = $this->getMockBuilder(Quote::class) - ->addMethods(['setIsMultiShipping', 'getIsMultiShipping']) - ->onlyMethods(['__wakeUp', 'getExtensionAttributes']) + $this->quoteMock = $this->getMockBuilder(CartInterface::class) + ->addMethods(['setTotalsCollectedFlag', 'getTotalsCollectedFlag']) ->disableOriginalConstructor() - ->getMock(); + ->getMockForAbstractClass(); $this->cartMock->expects($this->once()) ->method('getQuote') ->willReturn($this->quoteMock); - $this->object = new DisableMultishippingMode($this->cartMock); + $this->disableMultishippingMock = $this->createMock(DisableMultishippingModel::class); + $this->object = new DisableMultishippingMode( + $this->cartMock, + $this->disableMultishippingMock + ); } /** - * Tests turn off multishipping on multishipping quote. + * Test 'Disable Multishipping' plugin if 'Multishipping' mode is changed. * + * @param bool $totalsCollectedBefore * @return void + * @dataProvider pluginWithChangedMultishippingModeDataProvider */ - public function testExecuteTurnsOffMultishippingModeOnMultishippingQuote(): void + public function testPluginWithChangedMultishippingMode(bool $totalsCollectedBefore): void { $subject = $this->createMock(Index::class); - $extensionAttributes = $this->getMockBuilder(CartExtensionInterface::class) - ->disableOriginalConstructor() - ->setMethods(['setShippingAssignments', 'getShippingAssignments']) - ->getMockForAbstractClass(); - $extensionAttributes->method('getShippingAssignments') - ->willReturn( - $this->getMockForAbstractClass(ShippingAssignmentInterface::class) - ); - $extensionAttributes->expects($this->once()) - ->method('setShippingAssignments') - ->with([]); - $this->quoteMock->method('getExtensionAttributes') - ->willReturn($extensionAttributes); + $this->disableMultishippingMock->expects($this->once()) + ->method('execute') + ->with($this->quoteMock) + ->willReturn(true); $this->quoteMock->expects($this->once()) - ->method('getIsMultiShipping')->willReturn(1); - $this->quoteMock->expects($this->once()) - ->method('setIsMultiShipping') - ->with(0); + ->method('getTotalsCollectedFlag') + ->willReturn($totalsCollectedBefore); + $this->quoteMock->expects($totalsCollectedBefore ? $this->never() : $this->once()) + ->method('setTotalsCollectedFlag') + ->with(false); $this->cartMock->expects($this->once()) ->method('saveQuote'); @@ -87,16 +88,37 @@ public function testExecuteTurnsOffMultishippingModeOnMultishippingQuote(): void } /** - * Tests turn off multishipping on non-multishipping quote. + * DataProvider for testPluginWithChangedMultishippingMode(). + * + * @return array + */ + public function pluginWithChangedMultishippingModeDataProvider(): array + { + return [ + 'check_when_totals_are_collected' => [true], + 'check_when_totals_are_not_collected' => [false] + ]; + } + + /** + * Test 'Disable Multishipping' plugin if 'Multishipping' mode is NOT changed. * * @return void */ - public function testExecuteTurnsOffMultishippingModeOnNotMultishippingQuote(): void + public function testPluginWithNotChangedMultishippingMode(): void { $subject = $this->createMock(Index::class); - $this->quoteMock->expects($this->once())->method('getIsMultiShipping')->willReturn(0); - $this->quoteMock->expects($this->never())->method('setIsMultiShipping'); - $this->cartMock->expects($this->never())->method('saveQuote'); + $this->disableMultishippingMock->expects($this->once()) + ->method('execute') + ->with($this->quoteMock) + ->willReturn(false); + $this->quoteMock->expects($this->never()) + ->method('getTotalsCollectedFlag'); + $this->quoteMock->expects($this->never()) + ->method('setTotalsCollectedFlag'); + $this->cartMock->expects($this->never()) + ->method('saveQuote'); + $this->object->beforeExecute($subject); } } diff --git a/app/code/Magento/Multishipping/etc/frontend/events.xml b/app/code/Magento/Multishipping/etc/frontend/events.xml new file mode 100644 index 0000000000000..219e358528ca2 --- /dev/null +++ b/app/code/Magento/Multishipping/etc/frontend/events.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> + <event name="checkout_cart_save_before"> + <observer name="magento_multishipping_disabler" instance="Magento\Multishipping\Observer\DisableMultishippingObserver"/> + </event> +</config> diff --git a/dev/tests/integration/testsuite/Magento/Multishipping/Observer/DisableMultishippingObserverTest.php b/dev/tests/integration/testsuite/Magento/Multishipping/Observer/DisableMultishippingObserverTest.php new file mode 100644 index 0000000000000..3145f945b5009 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Multishipping/Observer/DisableMultishippingObserverTest.php @@ -0,0 +1,87 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Multishipping\Observer; + +use Magento\Checkout\Model\Cart; +use Magento\Checkout\Model\Session as CheckoutSession; +use Magento\Framework\ObjectManagerInterface; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Api\Data\ShippingAssignmentInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId; +use PHPUnit\Framework\TestCase; + +/** + * 'Disable Multishipping' observer integration tests. + * + * @magentoDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoAppArea frontend + */ +class DisableMultishippingObserverTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var Cart + */ + private $cart; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->cart = $this->objectManager->get(Cart::class); + $this->prepareQuote(); + } + + /** + * Test that Quote totals are calculated correctly when Cart is saved with 'Multishipping' mode enabled. + * + * @return void + */ + public function testObserverWithEnabledMultishippingMode(): void + { + $quote = $this->cart->getQuote(); + $extensionAttributes = $quote->getExtensionAttributes(); + $this->assertEquals(1, (int)$quote->getItemsQty()); + $this->assertCount(1, $extensionAttributes->getShippingAssignments()); + + $quote->setIsMultiShipping(1); + $quoteItem = current($quote->getItems()); + $itemData = [$quoteItem->getId() => ['qty' => 2]]; + + $this->cart->updateItems($itemData)->save(); + + $this->assertEquals(2, (int)$quote->getItemsQty()); + $this->assertEquals(0, $quote->getIsMultiShipping()); + $this->assertCount(0, $extensionAttributes->getShippingAssignments()); + } + + /** + * Prepare Quote before test execution. + * + * @return void + */ + private function prepareQuote(): void + { + /** @var CartInterface $quote */ + $quote = $this->objectManager->get(GetQuoteByReservedOrderId::class) + ->execute('test_order_with_simple_product_without_address'); + $shippingAssignment = $this->objectManager->get(ShippingAssignmentInterface::class); + $quote->getExtensionAttributes()->setShippingAssignments([$shippingAssignment]); + /** @var CheckoutSession $checkoutSession */ + $checkoutSession = $this->objectManager->get(CheckoutSession::class); + $checkoutSession->clearQuote(); + $checkoutSession->setQuoteId($quote->getId()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Multishipping/Plugin/DisableMultishippingModeTest.php b/dev/tests/integration/testsuite/Magento/Multishipping/Plugin/DisableMultishippingModeTest.php new file mode 100644 index 0000000000000..07e1fdd5a9d23 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Multishipping/Plugin/DisableMultishippingModeTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\Multishipping\Plugin; + +use Magento\Checkout\Model\Cart; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Data\Form\FormKey; +use Magento\TestFramework\TestCase\AbstractController; + +/** + * 'Disable Multishipping' plugin integration tests. + * + * @see DisableMultishippingMode + */ +class DisableMultishippingModeTest extends AbstractController +{ + /** + * @var Cart + */ + private $cart; + + /** + * @var FormKey + */ + private $formKey; + + /** + * @inheritDoc + */ + protected function setUp(): void + { + parent::setUp(); + + $this->cart = $this->_objectManager->get(Cart::class); + $this->formKey = $this->_objectManager->get(FormKey::class); + } + + /** + * Test that Quote totals are updated correctly when 'Multishipping' mode is enabled. + * + * @magentoDataFixture Magento/Catalog/_files/products.php + * @return void + */ + public function testPluginWithEnabledMultishippingMode(): void + { + $quote = $this->cart->getQuote(); + $postData = [ + 'qty' => '1', + 'product' => '1', + ]; + $this->getRequest()->setPostValue($postData) + ->setMethod(HttpRequest::METHOD_POST) + ->setParam('form_key', $this->formKey->getFormKey()); + + $this->dispatch('checkout/cart/add'); + $this->assertEquals(1, (int)$quote->getItemsQty()); + + $quote->setTotalsCollectedFlag(false) + ->setIsMultiShipping(true); + + $this->dispatch('checkout/cart/add'); + $this->assertEquals(2, (int)$quote->getItemsQty()); + $this->assertEquals(0, $quote->getIsMultiShipping()); + } +} From 5f775d2d58f9296aeac3b27788e95a8475824865 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 26 Oct 2020 13:30:51 +0200 Subject: [PATCH 39/59] MC-38589: [MFTF] AdminEnhancedMediaGalleryVerifyAssetFilterTest failed because of bad design --- .../AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml index 90ae7a5f10368..18c52a884c6eb 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> @@ -41,7 +41,7 @@ <argument name="id" value="$category.id$"/> </actionGroup> <actionGroup ref="AdminOpenMediaGalleryTinyMce4ActionGroup" stepKey="openMediaGalleryFromWysiwyg"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFridFilters"/> <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadFirstIMage"> <argument name="image" value="ImageUpload3"/> </actionGroup> @@ -56,7 +56,7 @@ <actionGroup ref="AdminSaveCategoryFormActionGroup" stepKey="saveCategory"/> <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultViewAgain"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFridFiltersAgain"/> <actionGroup ref="AdminEnhancedMediaGalleryCategoryGridExpandFilterActionGroup" stepKey="expandFilters"/> <actionGroup ref="AdminEnhancedMediaGallerySelectUsedInFilterActionGroup" stepKey="setUsedInFilter"> <argument name="filterName" value="Asset"/> From 0b2e2db10b41030e82ce8be0cd78a736d266b31c Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 26 Oct 2020 13:49:13 +0200 Subject: [PATCH 40/59] MC-38589: [MFTF] AdminEnhancedMediaGalleryVerifyAssetFilterTest failed because of bad design --- .../AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml index 18c52a884c6eb..a3208af0da238 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Test/AdminEnhancedMediaGalleryVerifyFilterByAssetTest.xml @@ -32,7 +32,7 @@ <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFridFilters"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilters"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> @@ -41,7 +41,7 @@ <argument name="id" value="$category.id$"/> </actionGroup> <actionGroup ref="AdminOpenMediaGalleryTinyMce4ActionGroup" stepKey="openMediaGalleryFromWysiwyg"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFridFilters"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilters"/> <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadFirstIMage"> <argument name="image" value="ImageUpload3"/> </actionGroup> @@ -56,7 +56,7 @@ <actionGroup ref="AdminSaveCategoryFormActionGroup" stepKey="saveCategory"/> <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> - <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFridFiltersAgain"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFiltersAgain"/> <actionGroup ref="AdminEnhancedMediaGalleryCategoryGridExpandFilterActionGroup" stepKey="expandFilters"/> <actionGroup ref="AdminEnhancedMediaGallerySelectUsedInFilterActionGroup" stepKey="setUsedInFilter"> <argument name="filterName" value="Asset"/> From 63737e339c457f9611efa7fb7be60a91c680099c Mon Sep 17 00:00:00 2001 From: OlgaVasyltsun <olga.vasyltsun@transoftgroup.com> Date: Tue, 27 Oct 2020 14:41:28 +0200 Subject: [PATCH 41/59] MC-38488: [MFTF] AdminMediaGalleryAssertUsedInLinkBlocksGridTest failed because of bad design --- ...minMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml index 63f6a483665c9..530605bb7e233 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertImageUsedInLinkBlocksGridTest.xml @@ -27,7 +27,7 @@ <deleteData createDataKey="createBlock" stepKey="deleteBlock"/> <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultViewAgain"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersOnStandaloneMediaGalleryPage"/> <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolderAgain"> <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> @@ -40,7 +40,7 @@ <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersOnMediaGalleryPage"/> <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImagesAfterTest"/> <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> </after> @@ -50,7 +50,7 @@ </actionGroup> <click selector="{{CmsWYSIWYGSection.InsertImageBtn}}" stepKey="clickInsertImageIcon" /> <waitForPageLoad stepKey="waitForInitialPageLoad" /> - <waitForPageLoad stepKey="waitForSecondaryPageLoad" /> + <waitForElementVisible selector="{{AdminMediaGalleryFolderSection.folderNewCreateButton}}" stepKey="waitForNewFolderButton"/> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFilter"/> <actionGroup ref="AdminMediaGalleryOpenNewFolderFormActionGroup" stepKey="openNewFolderForm"/> <actionGroup ref="AdminMediaGalleryCreateNewFolderActionGroup" stepKey="createNewFolder"> @@ -70,7 +70,7 @@ <click selector="{{BlockNewPagePageActionsSection.saveBlock}}" stepKey="saveBlock"/> <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openStandaloneMediaGallery"/> - <actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="resetAdminDataGridToDefaultView"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersOnStandaloneMediaGallery"/> <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectCreatedFolder"> <argument name="name" value="{{AdminMediaGalleryFolderData.name}}"/> </actionGroup> From 7569b08df6c47335f199a7226cb363f4ae562425 Mon Sep 17 00:00:00 2001 From: mastiuhin-olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Tue, 27 Oct 2020 17:37:17 +0200 Subject: [PATCH 42/59] MC-33288: [2.4][MSI][MFTF] StorefrontLoggedInCustomerCreateOrderAllOptionQuantityConfigurableProductCustomStockTest fails because of bad design --- .../Magento/Catalog/Model/ResourceModel/Product/Relation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php index deba2b555d5cc..2f8c4a34f0087 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php @@ -152,7 +152,7 @@ public function getRelationsByChildren(array $childrenIds): array )->join( ['relation' => $this->getTable('catalog_product_relation')], 'relation.parent_id = cpe.' . $linkField - )->where('child_id IN(?)', $childrenIds); + )->where('relation.child_id IN(?)', $childrenIds); return $connection->fetchCol($select); } From 647628ac00897af4d312d131f0cfd3ecd93b5fbf Mon Sep 17 00:00:00 2001 From: Andrii Beziazychnyi <a.beziazychnyi@atwix.com> Date: Tue, 27 Oct 2020 23:12:58 +0200 Subject: [PATCH 43/59] Backward Compatibility fixes --- .../QuoteGraphQl/Model/Resolver/MergeCarts.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php index d53ab597eaba4..297fd25be1fae 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/MergeCarts.php @@ -7,6 +7,7 @@ namespace Magento\QuoteGraphQl\Model\Resolver; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; @@ -50,19 +51,21 @@ class MergeCarts implements ResolverInterface /** * @param GetCartForUser $getCartForUser * @param CartRepositoryInterface $cartRepository - * @param CustomerCartResolver $customerCartResolver - * @param QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId + * @param CustomerCartResolver|null $customerCartResolver + * @param QuoteIdToMaskedQuoteIdInterface|null $quoteIdToMaskedQuoteId */ public function __construct( GetCartForUser $getCartForUser, CartRepositoryInterface $cartRepository, - CustomerCartResolver $customerCartResolver, - QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId + CustomerCartResolver $customerCartResolver = null, + QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId = null ) { $this->getCartForUser = $getCartForUser; $this->cartRepository = $cartRepository; - $this->customerCartResolver = $customerCartResolver; - $this->quoteIdToMaskedQuoteId = $quoteIdToMaskedQuoteId; + $this->customerCartResolver = $customerCartResolver + ?: ObjectManager::getInstance()->get(CustomerCartResolver::class); + $this->quoteIdToMaskedQuoteId = $quoteIdToMaskedQuoteId + ?: ObjectManager::getInstance()->get(QuoteIdToMaskedQuoteIdInterface::class); } /** From b47713413edc980fbdfb31d63a7f82d3e3504d8d Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Wed, 28 Oct 2020 12:59:32 +0200 Subject: [PATCH 44/59] MC-38651: [MFTF] AdminMediaGalleryAssertUsedInLinkPagesGridTest failed because of bad design --- ...inCmsPageFillOutBasicFieldsActionGroup.xml | 30 ++++++++ ...nSaveAndContinueEditCmsPageActionGroup.xml | 22 ++++++ .../SaveAndContinueEditCmsPageActionGroup.xml | 2 +- ...FillOutCustomCMSPageContentActionGroup.xml | 2 +- ...iaGalleryAssertUsedInLinkPagesGridTest.xml | 7 +- ...GalleryAssertUsedInLinkedPagesGridTest.xml | 75 ++++++++++++++++++ ...ediaGalleryCloseViewDetailsActionGroup.xml | 4 +- ...ediaGalleryDeletedAllImagesActionGroup.xml | 26 +++++++ ...ncedMediaGalleryUploadImageActionGroup.xml | 1 + ...ediaGalleryViewImageDetailsActionGroup.xml | 2 +- ...eryAssertFolderDoesNotExistActionGroup.xml | 4 +- ...ediaGalleryAssertFolderNameActionGroup.xml | 2 +- ...minMediaGalleryFolderDeleteActionGroup.xml | 4 +- ...minMediaGalleryFolderSelectActionGroup.xml | 8 +- ...ediaGalleryFromPageNoEditorActionGroup.xml | 2 +- .../Test/Mftf/Helper/MediaGalleryUiHelper.php | 77 +++++++++++++++++++ ...nhancedMediaGalleryImageActionsSection.xml | 2 +- ...nEnhancedMediaGalleryMassActionSection.xml | 1 + ...EnhancedMediaGalleryViewDetailsSection.xml | 3 +- .../AdminMediaGalleryFolderSection.xml | 8 +- .../AdminMediaGalleryMessagesSection.xml | 11 +++ 21 files changed, 273 insertions(+), 20 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCmsPageFillOutBasicFieldsActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndContinueEditCmsPageActionGroup.xml create mode 100644 app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php create mode 100644 app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCmsPageFillOutBasicFieldsActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCmsPageFillOutBasicFieldsActionGroup.xml new file mode 100644 index 0000000000000..52b4cee37b03c --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCmsPageFillOutBasicFieldsActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCmsPageFillOutBasicFieldsActionGroup"> + <annotations> + <description>Fills out the Page details (Page Title, Content and URL Key) on the Admin Page creation/edit page.</description> + </annotations> + <arguments> + <argument name="title" type="string" defaultValue="{{_defaultCmsPage.title}}"/> + <argument name="contentHeading" type="string" defaultValue="{{_defaultCmsPage.content_heading}}"/> + <argument name="content" type="string" defaultValue="{{_defaultCmsPage.content}}"/> + <argument name="urlKey" type="string" defaultValue="{{_defaultCmsPage.identifier}}"/> + </arguments> + + <fillField selector="{{CmsNewPagePageBasicFieldsSection.pageTitle}}" userInput="{{title}}" stepKey="fillTitle"/> + <conditionalClick selector="{{CmsNewPagePageContentSection.header}}" dependentSelector="{{CmsNewPagePageContentSection.contentHeading}}" visible="false" stepKey="expandContentTabIfCollapsed"/> + <fillField selector="{{CmsNewPagePageContentSection.contentHeading}}" userInput="{{contentHeading}}" stepKey="fillContentHeading"/> + <scrollTo selector="{{CmsNewPagePageContentSection.content}}" stepKey="scrollToPageContent"/> + <fillField selector="{{CmsNewPagePageContentSection.content}}" userInput="{{content}}" stepKey="fillContent"/> + <conditionalClick selector="{{CmsNewPagePageSeoSection.header}}" dependentSelector="{{CmsNewPagePageSeoSection.urlKey}}" visible="false" stepKey="clickExpandSearchEngineOptimisationIfCollapsed"/> + <fillField selector="{{CmsNewPagePageSeoSection.urlKey}}" userInput="{{urlKey}}" stepKey="fillUrlKey"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndContinueEditCmsPageActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndContinueEditCmsPageActionGroup.xml new file mode 100644 index 0000000000000..5c8b390b59ba0 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSaveAndContinueEditCmsPageActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSaveAndContinueEditCmsPageActionGroup"> + <annotations> + <description>Clicks on the Save and Continue button and see success message.</description> + </annotations> + + <scrollToTopOfPage stepKey="scrollToTopOfThePage"/> + <waitForElementVisible selector="{{CmsNewPagePageActionsSection.saveAndContinueEdit}}" stepKey="waitForSaveAndContinueButton"/> + <click selector="{{CmsNewPagePageActionsSection.saveAndContinueEdit}}" stepKey="clickSaveAndContinueButton"/> + <waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessage"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You saved the page." stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndContinueEditCmsPageActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndContinueEditCmsPageActionGroup.xml index a8dce19153a98..d5ccb4e1c1e71 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndContinueEditCmsPageActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/SaveAndContinueEditCmsPageActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="SaveAndContinueEditCmsPageActionGroup"> <annotations> - <description>Clicks on the Save and Continue button.</description> + <description>DEPRECATED. Use AdminSaveAndContinueEditCmsPageActionGroup instead. Clicks on the Save and Continue button.</description> </annotations> <waitForElementVisible time="10" selector="{{CmsNewPagePageActionsSection.saveAndContinueEdit}}" stepKey="waitForSaveAndContinueVisibility"/> diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/ActionGroup/FillOutCustomCMSPageContentActionGroup.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/ActionGroup/FillOutCustomCMSPageContentActionGroup.xml index f0938016d12f1..e0ec79394fdda 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/ActionGroup/FillOutCustomCMSPageContentActionGroup.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/ActionGroup/FillOutCustomCMSPageContentActionGroup.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="FillOutCustomCMSPageContentActionGroup"> <annotations> - <description>Fills out the Page details (Page Title, Content and URL Key)</description> + <description>DEPRECATED. Use AdminCmsPageFillOutBasicFieldsActionGroup and other AGs from CMS module. Fills out the Page details (Page Title, Content and URL Key)</description> </annotations> <arguments> diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkPagesGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkPagesGridTest.xml index 9b37a84122227..c29ddbae0eb52 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkPagesGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkPagesGridTest.xml @@ -7,16 +7,19 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminMediaGalleryAssertUsedInLinkPagesGridTest"> + <test name="AdminMediaGalleryAssertUsedInLinkPagesGridTest" deprecated="Use AdminMediaGalleryAssertUsedInLinkedPagesGridTest instead"> <annotations> <features value="AdminMediaGalleryUsedInBlocksFilter"/> <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1168"/> - <title value="Used in pages link"/> + <title value="DEPRECATED. Used in pages link"/> <stories value="Story 58: User sees entities where asset is used in" /> <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951848"/> <description value="User filters assets used in pages"/> <severity value="CRITICAL"/> <group value="media_gallery_ui"/> + <skip> + <issueId value="DEPRECATED">Use AdminMediaGalleryAssertUsedInLinkedPagesGridTest instead</issueId> + </skip> </annotations> <before> <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml new file mode 100644 index 0000000000000..2bf229d2a65d3 --- /dev/null +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml @@ -0,0 +1,75 @@ +<?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="AdminMediaGalleryAssertUsedInLinkedPagesGridTest"> + <annotations> + <features value="MediaGalleryCmsUi"/> + <stories value="Story 58: User sees entities where asset is used in" /> + <title value="Used in pages link"/> + <description value="User filters assets used in pages"/> + <severity value="CRITICAL"/> + <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1168"/> + <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1320712/scenarios/4951848"/> + <group value="media_gallery_ui"/> + </annotations> + + <before> + <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllMediaGalleryImages"/> + </before> + + <after> + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetMediaGalleryGridFilters"/> + <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectFolder"/> + <actionGroup ref="AdminMediaGalleryFolderDeleteActionGroup" stepKey="deleteFolder"/> + <actionGroup ref="AdminMediaGalleryAssertFolderDoesNotExistActionGroup" stepKey="assertFolderWasDeleted"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllMediaGalleryImages"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <actionGroup ref="AdminOpenCreateNewCMSPageActionGroup" stepKey="navigateToCreateNewPage"/> + <actionGroup ref="AdminCmsPageFillOutBasicFieldsActionGroup" stepKey="fillBasicPageFields"/> + <actionGroup ref="AdminOpenMediaGalleryFromPageNoEditorActionGroup" stepKey="openMediaGalleryForPage"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetMediaGalleryGridFilters"/> + <actionGroup ref="AdminMediaGalleryOpenNewFolderFormActionGroup" stepKey="openNewFolderForm"/> + <actionGroup ref="AdminMediaGalleryCreateNewFolderActionGroup" stepKey="createNewFolder"/> + <actionGroup ref="AdminMediaGalleryAssertFolderNameActionGroup" stepKey="assertNewFolderCreated"/> + <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="uploadImage"> + <argument name="image" value="ImageUpload3"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickImageInGridActionGroup" stepKey="selectContentImageInGrid"> + <argument name="imageName" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickAddSelectedActionGroup" stepKey="clickAddSelectedContentImage"/> + <actionGroup ref="AdminSaveAndContinueEditCmsPageActionGroup" stepKey="saveCmsPageAndContinue"/> + + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openStandaloneMediaGallery"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetMediaGalleryGridFiltersAgain"/> + <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectFolder"/> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetails"/> + <actionGroup ref="AdminEnhancedMediaGalleryClickEntityUsedInActionGroup" stepKey="clickUsedInPages"> + <argument name="entityName" value="Pages"/> + </actionGroup> + <actionGroup ref="AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup" stepKey="assertFilterApplied"> + <argument name="filterPlaceholder" value="{{ImageMetadata.title}}"/> + </actionGroup> + <actionGroup ref="AdminDeleteCmsPageFromGridActionGroup" stepKey="deleteCmsPage"> + <argument name="urlKey" value="{{_defaultCmsPage.identifier}}"/> + </actionGroup> + + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersInPageGrid"/> + <actionGroup ref="AdminOpenStandaloneMediaGalleryActionGroup" stepKey="openMediaGallery"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="resetMediaGalleryGridFiltersAndAgain"/> + <actionGroup ref="AdminMediaGalleryFolderSelectActionGroup" stepKey="selectFolderAgain"/> + <actionGroup ref="AdminEnhancedMediaGalleryViewImageDetails" stepKey="openViewImageDetailsToVerifyEmptyUsedIn"/> + <actionGroup ref="AssertAdminEnhancedMediaGalleryUsedInSectionNotDisplayedActionGroup" stepKey="assertThereIsNoUsedInSection"/> + <actionGroup ref="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup" stepKey="closeDetails"/> + </test> +</tests> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryCloseViewDetailsActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryCloseViewDetailsActionGroup.xml index 3754eb319da44..effb574853bb7 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryCloseViewDetailsActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryCloseViewDetailsActionGroup.xml @@ -10,10 +10,10 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminEnhancedMediaGalleryCloseViewDetailsActionGroup"> <annotations> - <description>Closes View Details panel</description> + <description>Closes View Details panel of Media Gallery image.</description> </annotations> <click selector="{{AdminEnhancedMediaGalleryViewDetailsSection.cancel}}" stepKey="clickCancel"/> - <wait time="1" stepKey="waitForElementRender"/> + <waitForElementNotVisible selector="{{AdminEnhancedMediaGalleryViewDetailsSection.modalTitle}}" stepKey="waitForElementRender"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml new file mode 100644 index 0000000000000..4aa460327578a --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryDeletedAllImagesActionGroup.xml @@ -0,0 +1,26 @@ +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <actionGroup name="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup"> + <annotations> + <description>Open Media Gallery page and delete all images</description> + </annotations> + <amOnPage url="{{AdminStandaloneMediaGalleryPage.url}}" stepKey="openMediaGalleryPage"/> + <!-- It sometimes is loading too long for default 10s --> + <waitForPageLoad time="60" stepKey="waitForPageFullyLoaded"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingFilters"/> + <helper class="\Magento\MediaGalleryUi\Test\Mftf\Helper\MediaGalleryUiHelper" method="deleteAllImagesUsingMassAction" stepKey="deleteAllImagesUsingMassAction"> + <argument name="emptyRow">{{AdminMediaGalleryGridSection.noDataMessage}}</argument> + <argument name="deleteImagesButton">{{AdminEnhancedMediaGalleryMassActionSection.deleteImages}}</argument> + <argument name="checkImage">{{AdminEnhancedMediaGalleryMassActionSection.massActionCheckboxAll}}</argument> + <argument name="deleteSelectedButton">{{AdminEnhancedMediaGalleryMassActionSection.deleteSelected}}</argument> + <argument name="modalAcceptButton">{{AdminEnhancedMediaGalleryDeleteModalSection.confirmDelete}}</argument> + <argument name="successMessageContainer">{{AdminMediaGalleryMessagesSection.success}}</argument> + <argument name="successMessage">been successfully deleted</argument> + </helper> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryUploadImageActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryUploadImageActionGroup.xml index 053a1185b3fda..9a9c09cda9ab2 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryUploadImageActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryUploadImageActionGroup.xml @@ -17,6 +17,7 @@ <argument name="image"/> </arguments> + <waitForPageLoad stepKey="waitForPageFullyLoaded"/> <attachFile selector="{{AdminEnhancedMediaGalleryActionsSection.upload}}" userInput="{{image.value}}" stepKey="uploadImage"/> <waitForPageLoad stepKey="waitForPageLoad"/> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryViewImageDetailsActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryViewImageDetailsActionGroup.xml index b5c0bbac69bec..d216af75c7be1 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryViewImageDetailsActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminEnhancedMediaGalleryViewImageDetailsActionGroup.xml @@ -15,6 +15,6 @@ <click selector="{{AdminEnhancedMediaGalleryImageActionsSection.openContextMenu}}" stepKey="openContextMenu"/> <click selector="{{AdminEnhancedMediaGalleryImageActionsSection.viewDetails}}" stepKey="viewDetails"/> - <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/> + <waitForElementVisible selector="{{AdminEnhancedMediaGalleryViewDetailsSection.modalTitle}}" stepKey="waitForLoadingMaskToDisappear"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderDoesNotExistActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderDoesNotExistActionGroup.xml index d0d9817da6d34..488ea03ebd86c 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderDoesNotExistActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderDoesNotExistActionGroup.xml @@ -12,7 +12,7 @@ <arguments> <argument name="name" type="string" defaultValue="{{AdminMediaGalleryFolderData.name}}"/> </arguments> - <wait time="5" stepKey="waitForFolderTreeReloads"/> - <dontSeeElement selector="//div[contains(@class, 'media-directory-container')]//a[contains(text(), '{{name}}')]" stepKey="folderDoesNotExist"/> + <waitForPageLoad stepKey="waitForFolderTreeReloads"/> + <dontSeeElement selector="{{AdminMediaGalleryFolderSection.folderInTree(name)}}" stepKey="folderDoesNotExist"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderNameActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderNameActionGroup.xml index 7d71c764bc8de..e42eb31dc00d8 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderNameActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryAssertFolderNameActionGroup.xml @@ -12,6 +12,6 @@ <arguments> <argument name="name" type="string" defaultValue="{{AdminMediaGalleryFolderData.name}}"/> </arguments> - <waitForElementVisible selector="//div[contains(@class, 'media-directory-container')]//a[contains(text(), '{{name}}')]" stepKey="waitForFolder"/> + <waitForElementVisible selector="{{AdminMediaGalleryFolderSection.folderInTree(name)}}" stepKey="waitForFolder"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderDeleteActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderDeleteActionGroup.xml index f7e8f551e681f..398003c7f2b02 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderDeleteActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderDeleteActionGroup.xml @@ -9,8 +9,8 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminMediaGalleryFolderDeleteActionGroup"> - <wait time="2" stepKey="waitBeforeDeleteButtonWillBeActive"/> - <click selector="{{AdminMediaGalleryFolderSection.folderDeleteButton}}" stepKey="clickDeleteButton"/> + <waitForElementVisible selector="{{AdminMediaGalleryFolderSection.folderDeleteButtonActive}}" stepKey="waitBeforeDeleteButtonWillBeActive"/> + <click selector="{{AdminMediaGalleryFolderSection.folderDeleteButtonActive}}" stepKey="clickDeleteButton"/> <waitForElementVisible selector="{{AdminMediaGalleryFolderSection.folderDeleteModalHeader}}" stepKey="waitBeforeModalAppears"/> <click selector="{{AdminMediaGalleryFolderSection.folderConfirmDeleteButton}}" stepKey="clickConfirmDeleteButton"/> </actionGroup> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderSelectActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderSelectActionGroup.xml index b8ed1d4f1cd25..5751b8ec323da 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderSelectActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryFolderSelectActionGroup.xml @@ -9,11 +9,15 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminMediaGalleryFolderSelectActionGroup"> + <annotations> + <description>Wait for folder name appeared in tree and then click it.</description> + </annotations> <arguments> <argument name="name" type="string" defaultValue="{{AdminMediaGalleryFolderData.name}}"/> </arguments> - <wait time="2" stepKey="waitBeforeClickOnFolder"/> - <click selector="//div[contains(@class, 'media-directory-container')]//a[contains(text(), '{{name}}')]" stepKey="selectFolder"/> + + <waitForElementVisible selector="{{AdminMediaGalleryFolderSection.folderInTree(name)}}" stepKey="waitBeforeClickOnFolder"/> + <click selector="{{AdminMediaGalleryFolderSection.folderInTree(name)}}" stepKey="selectFolder"/> <waitForLoadingMaskToDisappear stepKey="waitForFolderContents"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromPageNoEditorActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromPageNoEditorActionGroup.xml index a434aa72679e4..287b6219115f2 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromPageNoEditorActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminOpenMediaGalleryFromPageNoEditorActionGroup.xml @@ -9,7 +9,7 @@ <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminOpenMediaGalleryFromPageNoEditorActionGroup"> - <click selector="{{CmsNewPagePageContentSection.header}}" stepKey="clickExpandContent"/> + <conditionalClick selector="{{CmsNewPagePageContentSection.header}}" dependentSelector="{{CmsNewPagePageContentSection.contentHeading}}" visible="false" stepKey="clickExpandContent"/> <waitForElementVisible selector="{{CmsWYSIWYGSection.InsertImageBtn}}" stepKey="waitForInsertImageButton" /> <scrollTo selector="{{CmsWYSIWYGSection.InsertImageBtn}}" x="0" y="-80" stepKey="scrollToInsertImageButton"/> <click selector="{{CmsWYSIWYGSection.InsertImageBtn}}" stepKey="clickInsertImage" /> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php b/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php new file mode 100644 index 0000000000000..4059a8460bb51 --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Helper/MediaGalleryUiHelper.php @@ -0,0 +1,77 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\MediaGalleryUi\Test\Mftf\Helper; + +use Facebook\WebDriver\Remote\RemoteWebDriver as FacebookWebDriver; +use Facebook\WebDriver\Remote\RemoteWebElement; +use Facebook\WebDriver\WebDriverBy; +use Magento\FunctionalTestingFramework\Helper\Helper; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; + +/** + * Class for MFTF helpers for MediaGalleryUi module. + */ +class MediaGalleryUiHelper extends Helper +{ + /** + * Delete all images using mass action. + * + * @param string $emptyRow + * @param string $deleteImagesButton + * @param string $checkImage + * @param string $deleteSelectedButton + * @param string $modalAcceptButton + * @param string $successMessageContainer + * @param string $successMessage + * + * @return void + */ + public function deleteAllImagesUsingMassAction( + string $emptyRow, + string $deleteImagesButton, + string $checkImage, + string $deleteSelectedButton, + string $modalAcceptButton, + string $successMessageContainer, + string $successMessage + ): void { + try { + /** @var MagentoWebDriver $webDriver */ + $magentoWebDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + /** @var FacebookWebDriver $webDriver */ + $webDriver = $magentoWebDriver->webDriver; + $rows = $webDriver->findElements(WebDriverBy::cssSelector($emptyRow)); + while (empty($rows)) { + $magentoWebDriver->click($deleteImagesButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($deleteSelectedButton, 10); + + // Check all images + /** @var RemoteWebElement[] $images */ + $imagesCheckboxes = $webDriver->findElements(WebDriverBy::cssSelector($checkImage)); + /** @var RemoteWebElement $image */ + foreach ($imagesCheckboxes as $imageCheckbox) { + $imageCheckbox->click(); + } + + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->click($deleteSelectedButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($modalAcceptButton, 10); + $magentoWebDriver->click($modalAcceptButton); + $magentoWebDriver->waitForPageLoad(60); + $magentoWebDriver->waitForElementVisible($successMessageContainer, 10); + $magentoWebDriver->see($successMessage, $successMessageContainer); + + $rows = $webDriver->findElements(WebDriverBy::cssSelector($emptyRow)); + } + } catch (\Exception $e) { + $this->fail($e->getMessage()); + } + } +} diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml index f36fca88dc760..1a8f6f553d4ce 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryImageActionsSection.xml @@ -10,7 +10,7 @@ <section name="AdminEnhancedMediaGalleryImageActionsSection"> <element name="openContextMenu" type="button" selector=".three-dots"/> <element name="contextMenuItem" type="block" selector="//div[@class='media-gallery-image']//ul[@class='action-menu _active']//li//a[@class='action-menu-item']"/> - <element name="viewDetails" type="button" selector="[data-ui-id='action-image-details']"/> + <element name="viewDetails" type="button" selector="//ul[@class='action-menu _active']//a[text()='View Details']" timeout="30"/> <element name="delete" type="button" selector="[data-ui-id='action-delete']"/> <element name="edit" type="button" selector="[data-ui-id='action-edit']"/> <element name="imageInGrid" type="button" selector="//li[@data-ui-id='title'and text()='{{imageTitle}}']/parent::*/parent::*/parent::div//img[@class='media-gallery-image-column']" parameterized="true"/> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml index 07f2dc23530e1..9018ccb4ddd69 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryMassActionSection.xml @@ -13,5 +13,6 @@ <element name="cancelMassActionMode" type="button" selector="#cancel_massaction"/> <element name="deleteImages" type="button" selector="#delete_massaction"/> <element name="deleteSelected" type="button" selector="#delete_selected_massaction"/> + <element name="massActionCheckboxAll" type="checkbox" selector="[data-id='media-gallery-masonry-grid'] .mediagallery-massaction-checkbox input[type='checkbox']"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml index 92f3323214065..9b9dc157bbc27 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminEnhancedMediaGalleryViewDetailsSection.xml @@ -8,6 +8,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="AdminEnhancedMediaGalleryViewDetailsSection"> + <element name="modalTitle" type="text" selector="//aside[contains(@class, 'media-gallery-image-details') and contains(@class, '_show')]//header[contains(@class, 'modal-header')]//h1[contains(@class, 'modal-title') and contains(., 'Image Details')]"/> <element name="title" type="text" selector=".image-title"/> <element name="contentType" type="text" selector="span[data-ui-id='content-type']"/> <element name="type" type="text" selector="//div[@class='attribute']/span[contains(text(), 'Type')]/following-sibling::div"/> @@ -22,7 +23,7 @@ <element name="usedIn" type="button" selector="//div[@class='attribute']/span[contains(text(), 'Used In')]"/> <element name="updatedAtDate" type="button" selector="//div[@class='attribute']/span[contains(text(), 'Modified')]/following-sibling::div"/> <element name="addImage" type="button" selector=".add-image-action"/> - <element name="cancel" type="button" selector="#image-details-action-cancel"/> + <element name="cancel" type="button" selector="#image-details-action-cancel" timeout="10"/> <element name="usedInLink" type="button" parameterized="true" selector="//div[@class='attribute']/span[contains(text(), 'Used In')]/following-sibling::div/a[contains(text(), '{{entityName}}')]"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml index 2e6919f692042..acc378dac6e67 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml @@ -12,13 +12,15 @@ <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"/> - <element name="folderDeleteButton" type="button" selector="#delete_folder"/> - <element name="folderConfirmDeleteButton" type="button" selector="//footer//button/span[contains(text(), 'OK')]"/> + <element name="folderDeleteButton" type="button" selector="#delete_folder" timeout="30"/> + <element name="folderDeleteButtonActive" type="button" selector="#delete_folder:not(.disabled)" timeout="30"/> + <element name="folderConfirmDeleteButton" type="button" selector="//footer//button/span[contains(text(), 'OK')]" timeout="30"/> <element name="folderCancelDeleteButton" type="button" selector="//footer//button/span[contains(text(), 'Cancel')]"/> <element name="folderNameField" type="button" selector="[name=folder_name]"/> - <element name="folderConfirmCreateButton" type="button" selector="//button/span[contains(text(),'Confirm')]"/> + <element name="folderConfirmCreateButton" type="button" selector="//button/span[contains(text(),'Confirm')]" timeout="30"/> <element name="folderNameValidationMessage" type="block" selector="label.mage-error"/> <element name="folderArrow" type="button" selector="#{{id}} > .jstree-icon" parameterized="true"/> <element name="checkIfFolderArrowExpand" type="button" selector="//li[@id='{{id}}' and contains(@class,'jstree-closed')]" parameterized="true"/> + <element name="folderInTree" type="text" selector="//div[contains(@class, 'media-directory-container')]//ul//li//a[contains(text(), '{{name}}')]" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml new file mode 100644 index 0000000000000..659fb51080225 --- /dev/null +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryMessagesSection.xml @@ -0,0 +1,11 @@ +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <section name="AdminMediaGalleryMessagesSection"> + <element name="success" type="text" selector=".media-gallery-container ul.messages div.message.message-success span"/> + </section> +</sections> From 87d936894839ac92528b6f4fcf476ee2ba4eb550 Mon Sep 17 00:00:00 2001 From: Vitaliy Prokopov <vitaliyprokopov@Vitaliys-MacBook-Pro.local> Date: Wed, 28 Oct 2020 16:16:27 +0200 Subject: [PATCH 45/59] fixed url issue for image --- .../Model/Resolver/Category/Image.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Image.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Image.php index 5de7fdc10ff4a..549b1311000ec 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Image.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Image.php @@ -7,14 +7,16 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Category; +use Magento\Catalog\Model\Category; +use Magento\Catalog\Model\Category\FileInfo; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem\DirectoryList; use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\UrlInterface; use Magento\Store\Api\Data\StoreInterface; -use Magento\Framework\Filesystem\DirectoryList; -use Magento\Catalog\Model\Category\FileInfo; -use Magento\Framework\GraphQl\Exception\GraphQlInputException; /** * Resolve category image to a fully qualified URL @@ -52,7 +54,7 @@ public function resolve( if (!isset($value['model'])) { throw new LocalizedException(__('"model" value should be specified')); } - /** @var \Magento\Catalog\Model\Category $category */ + /** @var Category $category */ $category = $value['model']; $imagePath = $category->getData('image'); if (empty($imagePath)) { @@ -60,7 +62,7 @@ public function resolve( } /** @var StoreInterface $store */ $store = $context->getExtensionAttributes()->getStore(); - $baseUrl = $store->getBaseUrl(); + $baseUrl = $store->getBaseUrl(UrlInterface::URL_TYPE_WEB); $filenameWithMedia = $this->fileInfo->isBeginsWithMediaDirectoryPath($imagePath) ? $imagePath : $this->formatFileNameWithMediaCategoryFolder($imagePath); From 5ef4711270360c3b418f38a1c05730919a5dd91f Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 29 Oct 2020 12:01:35 +0200 Subject: [PATCH 46/59] MC-38589: [MFTF] AdminEnhancedMediaGalleryVerifyAssetFilterTest failed because of bad design --- .../AdminMediaGalleryClickAddSelectedActionGroup.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml index f575e346a8ca0..711a271c9d4ec 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml @@ -10,8 +10,8 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> <actionGroup name="AdminMediaGalleryClickAddSelectedActionGroup"> <waitForElementVisible selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="waitForAddSelectedButton"/> - <click selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="clickAddSelected"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - <waitForElementVisible selector="{{MediaGallerySection.insertEditImageModalWindow}}" stepKey="waitForInsertEditImageWindow"/> + <click selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="ClickAddSelected"/> + <waitForPageLoad stepKey="waitForImageToBeAdded"/> + <waitForElementVisible selector="{{MediaGallerySection.insertEditImageModalWindow}}" stepKey="waitForLoadingMaskDisappear"/> </actionGroup> </actionGroups> From 07062f4ad5d5f8d3d5b52b4e080d8ec76fd2f316 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 29 Oct 2020 12:40:17 +0200 Subject: [PATCH 47/59] MC-37213: [MFTF] AdminMediaGalleryCatalogUiUsedInProductFilterTest is flaky --- .../Test/Mftf/Suite/MediaGalleryUiSuite.xml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml index bda9b6ad08e43..e81dc807d0f48 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Suite/MediaGalleryUiSuite.xml @@ -11,12 +11,16 @@ <suite name="MediaGalleryUiSuite"> <before> <actionGroup ref="AdminDisableWYSIWYGActionGroup" stepKey="disableWYSIWYG" /> - <magentoCLI command="config:set {{MediaGalleryConfigDataEnabled.path}} {{MediaGalleryConfigDataEnabled.value}}" stepKey="enableEnhancedMediaGallery"/> - <magentoCLI command="config:set {{MediaGalleryRenditionsDataEnabled.path}} {{MediaGalleryRenditionsDataEnabled.value}}" stepKey="enableMediaGalleryRenditions"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminMediaGalleryEnhancedEnableActionGroup" stepKey="enableEnhancedMediaGallery"> + <argument name="enabled" value="1"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryRenditionsEnableActionGroup" stepKey="enableMediaGalleryRenditions"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/> </before> <after> - <magentoCLI command="config:set {{MediaGalleryRenditionsDataDisabled.path}} {{MediaGalleryRenditionsDataDisabled.value}}" stepKey="disableMediaGalleryRenditions"/> - <magentoCLI command="config:set {{MediaGalleryConfigDataDisabled.path}} {{MediaGalleryConfigDataDisabled.value}}" stepKey="disableEnhancedMediaGallery"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminMediaGalleryEnhancedEnableActionGroup" stepKey="disableEnhancedMediaGallery"/> <actionGroup ref="AdminEnableWYSIWYGActionGroup" stepKey="enableWYSIWYG" /> </after> <include> From 871e62d023b3b227153a8d82bdc22d7ac25862d2 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 29 Oct 2020 15:43:07 +0200 Subject: [PATCH 48/59] MC-38651: [MFTF] AdminMediaGalleryAssertUsedInLinkPagesGridTest failed because of bad design --- .../Test/Mftf/Section/AdminMediaGalleryFolderSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml index acc378dac6e67..be12829229663 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/Section/AdminMediaGalleryFolderSection.xml @@ -21,6 +21,6 @@ <element name="folderNameValidationMessage" type="block" selector="label.mage-error"/> <element name="folderArrow" type="button" selector="#{{id}} > .jstree-icon" parameterized="true"/> <element name="checkIfFolderArrowExpand" type="button" selector="//li[@id='{{id}}' and contains(@class,'jstree-closed')]" parameterized="true"/> - <element name="folderInTree" type="text" selector="//div[contains(@class, 'media-directory-container')]//ul//li//a[contains(text(), '{{name}}')]" parameterized="true"/> + <element name="folderInTree" type="text" selector="//div[contains(@class, 'media-directory-container')]//ul//li//a[normalize-space(text())='{{name}}']" parameterized="true"/> </section> </sections> From ecf59ac44640a8b3af9d391c3bdb87f22c7d171e Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Thu, 29 Oct 2020 15:46:14 +0200 Subject: [PATCH 49/59] MC-38651: [MFTF] AdminMediaGalleryAssertUsedInLinkPagesGridTest failed because of bad design --- .../Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml index 2bf229d2a65d3..539d6ccb6c0dd 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml @@ -20,7 +20,7 @@ </annotations> <before> - <actionGroup ref="AdminLoginActionGroup" stepKey="login"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllMediaGalleryImages"/> </before> From 3a95f15db88c04747fcc838aba909c09de00252f Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 29 Oct 2020 11:41:41 -0500 Subject: [PATCH 50/59] MC-37726: Price filter uses base currency for ranges --- .../GraphQl/Catalog/ProductPriceTest.php | 60 +++++++++++++++++-- .../Catalog/ProductSearchAggregationsTest.php | 31 ++-------- 2 files changed, 60 insertions(+), 31 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php index f1c1be44ccd13..7a3829a325c59 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php @@ -78,6 +78,54 @@ public function testProductWithSinglePrice() $this->assertPrices($expectedPriceRange, $product['price_range']); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/products.php + * @magentoConfigFixture default_store currency/options/allow EUR,USD + */ + public function testProductWithSinglePriceNonDefaultCurrency() + { + $skus = ['simple']; + $query = $this->getProductQuery($skus); + $headerMap = [ + 'Content-Currency' => 'EUR' + ]; + $result = $this->graphQlQuery($query, [], '', $headerMap); + + $this->assertArrayNotHasKey('errors', $result); + $this->assertNotEmpty($result['products']['items']); + $product = $result['products']['items'][0]; + $this->assertNotEmpty($product['price_range']); + + $expectedPriceRange = [ + "minimum_price" => [ + "regular_price" => [ + "value" => 20 + ], + "final_price" => [ + "value" => 20 + ], + "discount" => [ + "amount_off" => 0, + "percent_off" => 0 + ] + ], + "maximum_price" => [ + "regular_price" => [ + "value" => 20 + ], + "final_price" => [ + "value" => 20 + ], + "discount" => [ + "amount_off" => 0, + "percent_off" => 0 + ] + ] + ]; + + $this->assertPrices($expectedPriceRange, $product['price_range'], 'EUR'); + } + /** * Pricing for Simple, Grouped and Configurable products with no special or tier prices configured * @@ -909,7 +957,7 @@ private function getQueryConfigurableProductAndVariants(array $sku): string name sku price_range { - minimum_price {regular_price + minimum_price {regular_price { value currency @@ -949,13 +997,13 @@ private function getQueryConfigurableProductAndVariants(array $sku): string ... on ConfigurableProduct{ variants{ product{ - + sku price_range { minimum_price {regular_price {value} final_price { value - + } discount { amount_off @@ -965,11 +1013,11 @@ private function getQueryConfigurableProductAndVariants(array $sku): string maximum_price { regular_price { value - + } final_price { value - + } discount { amount_off @@ -985,7 +1033,7 @@ private function getQueryConfigurableProductAndVariants(array $sku): string final_price{value} quantity } - + } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php index 075388b0f023c..57b6b24472bf7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php @@ -89,31 +89,12 @@ function ($a) { } /** - * @magentoApiDataFixture Magento/Store/_files/second_store_with_second_currency.php * @magentoApiDataFixture Magento/Catalog/_files/products_for_search.php + * @magentoConfigFixture default_store currency/options/allow EUR,USD */ public function testAggregationPriceRangesWithCurrencyHeader() { - // add USD as allowed (not default) currency - $objectManager = Bootstrap::getObjectManager(); - /* @var Store $store */ - $store = $objectManager->create(Store::class); - $store->load('fixture_second_store'); - /** @var Config $configResource */ - $configResource = $objectManager->get(Config::class); - $configResource->saveConfig( - Currency::XML_PATH_CURRENCY_ALLOW, - 'USD', - ScopeInterface::SCOPE_STORES, - $store->getId() - ); - // Configuration cache clean is required to reload currency setting - /** @var System $config */ - $config = $objectManager->get(System::class); - $config->clean(); - - $headerMap['Store'] = 'fixture_second_store'; - $headerMap['Content-Currency'] = 'USD'; + $headerMap['Content-Currency'] = 'EUR'; $query = $this->getGraphQlQuery( '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"' ); @@ -131,10 +112,10 @@ function ($a) { $this->assertEquals('Price', $priceAggregation['label']); $this->assertEquals(4, $priceAggregation['count']); $expectedOptions = [ - ['label' => '10-20', 'value'=> '10_20', 'count' => '2'], - ['label' => '20-30', 'value'=> '20_30', 'count' => '1'], - ['label' => '30-40', 'value'=> '30_40', 'count' => '1'], - ['label' => '40-50', 'value'=> '40_50', 'count' => '1'] + ['label' => '20-40', 'value'=> '20_40', 'count' => '2'], + ['label' => '40-60', 'value'=> '40_60', 'count' => '1'], + ['label' => '60-80', 'value'=> '60_80', 'count' => '1'], + ['label' => '80-100', 'value'=> '80_100', 'count' => '1'] ]; $this->assertEquals($expectedOptions, $priceAggregation['options']); } From d835452dd2d859c43ad149ece77390a879a6ddda Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 29 Oct 2020 12:46:40 -0500 Subject: [PATCH 51/59] MC-37726: Price filter uses base currency for ranges --- .../Magento/GraphQl/Catalog/ProductPriceTest.php | 15 ++++++++------- .../Catalog/ProductSearchAggregationsTest.php | 13 +++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php index 7a3829a325c59..b6c4b55dc1d23 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductPriceTest.php @@ -80,14 +80,15 @@ public function testProductWithSinglePrice() /** * @magentoApiDataFixture Magento/Catalog/_files/products.php - * @magentoConfigFixture default_store currency/options/allow EUR,USD + * @magentoApiDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoConfigFixture default_store currency/options/allow CNY,USD */ public function testProductWithSinglePriceNonDefaultCurrency() { $skus = ['simple']; $query = $this->getProductQuery($skus); $headerMap = [ - 'Content-Currency' => 'EUR' + 'Content-Currency' => 'CNY' ]; $result = $this->graphQlQuery($query, [], '', $headerMap); @@ -99,10 +100,10 @@ public function testProductWithSinglePriceNonDefaultCurrency() $expectedPriceRange = [ "minimum_price" => [ "regular_price" => [ - "value" => 20 + "value" => 70 ], "final_price" => [ - "value" => 20 + "value" => 70 ], "discount" => [ "amount_off" => 0, @@ -111,10 +112,10 @@ public function testProductWithSinglePriceNonDefaultCurrency() ], "maximum_price" => [ "regular_price" => [ - "value" => 20 + "value" => 70 ], "final_price" => [ - "value" => 20 + "value" => 70 ], "discount" => [ "amount_off" => 0, @@ -123,7 +124,7 @@ public function testProductWithSinglePriceNonDefaultCurrency() ] ]; - $this->assertPrices($expectedPriceRange, $product['price_range'], 'EUR'); + $this->assertPrices($expectedPriceRange, $product['price_range'], 'CNY'); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php index 57b6b24472bf7..9ff33795cb868 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php @@ -90,11 +90,12 @@ function ($a) { /** * @magentoApiDataFixture Magento/Catalog/_files/products_for_search.php - * @magentoConfigFixture default_store currency/options/allow EUR,USD + * @magentoApiDataFixture Magento/Directory/_files/usd_cny_rate.php + * @magentoConfigFixture default_store currency/options/allow CNY,USD */ public function testAggregationPriceRangesWithCurrencyHeader() { - $headerMap['Content-Currency'] = 'EUR'; + $headerMap['Content-Currency'] = 'CNY'; $query = $this->getGraphQlQuery( '"search_product_1", "search_product_2", "search_product_3", "search_product_4" ,"search_product_5"' ); @@ -112,10 +113,10 @@ function ($a) { $this->assertEquals('Price', $priceAggregation['label']); $this->assertEquals(4, $priceAggregation['count']); $expectedOptions = [ - ['label' => '20-40', 'value'=> '20_40', 'count' => '2'], - ['label' => '40-60', 'value'=> '40_60', 'count' => '1'], - ['label' => '60-80', 'value'=> '60_80', 'count' => '1'], - ['label' => '80-100', 'value'=> '80_100', 'count' => '1'] + ['label' => '70-140', 'value'=> '70_140', 'count' => '2'], + ['label' => '140-210', 'value'=> '140_210', 'count' => '1'], + ['label' => '210-280', 'value'=> '210_280', 'count' => '1'], + ['label' => '280-350', 'value'=> '280_350', 'count' => '1'] ]; $this->assertEquals($expectedOptions, $priceAggregation['options']); } From 908456b80bc687c8268e3c5ec9d4cfaa14c65999 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 29 Oct 2020 12:55:24 -0500 Subject: [PATCH 52/59] MC-37726: Price filter uses base currency for ranges --- .../GraphQl/Catalog/ProductSearchAggregationsTest.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php index 9ff33795cb868..bd4530d0724a1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductSearchAggregationsTest.php @@ -7,12 +7,6 @@ namespace Magento\GraphQl\Catalog; -use Magento\Config\App\Config\Type\System; -use Magento\Config\Model\ResourceModel\Config; -use Magento\Directory\Model\Currency; -use Magento\Store\Model\ScopeInterface; -use Magento\Store\Model\Store; -use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; class ProductSearchAggregationsTest extends GraphQlAbstract From 44fa566db29f8a1911e64371b06849587e60d1d9 Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 29 Oct 2020 15:59:21 -0500 Subject: [PATCH 53/59] MC-37726: Price filter uses base currency for ranges --- app/code/Magento/CatalogGraphQl/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogGraphQl/composer.json b/app/code/Magento/CatalogGraphQl/composer.json index 46d7454a6d7e2..463f974056749 100644 --- a/app/code/Magento/CatalogGraphQl/composer.json +++ b/app/code/Magento/CatalogGraphQl/composer.json @@ -7,6 +7,7 @@ "magento/module-eav": "*", "magento/module-catalog": "*", "magento/module-catalog-inventory": "*", + "magento/module-directory": "*", "magento/module-search": "*", "magento/module-store": "*", "magento/module-eav-graph-ql": "*", From ebbf23a009ff0a65456512f9ab1502af8b638123 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Thu, 29 Oct 2020 16:00:05 -0500 Subject: [PATCH 54/59] added tests for seo disabled --- .../Catalog/CategoriesQuery/CategoriesFilterTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoriesQuery/CategoriesFilterTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoriesQuery/CategoriesFilterTest.php index a3daf89631c17..09f39bf1441f5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoriesQuery/CategoriesFilterTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/CategoriesQuery/CategoriesFilterTest.php @@ -395,8 +395,9 @@ public function testMinimumMatchQueryLength() * Test category image full name is returned * * @magentoApiDataFixture Magento/Catalog/_files/catalog_category_with_long_image_name.php + * @magentoConfigFixture default_store web/seo/use_rewrites 0 */ - public function testCategoryImageName() + public function testCategoryImageNameAndSeoDisabled() { /** @var CategoryCollection $categoryCollection */ $categoryCollection = Bootstrap::getObjectManager()->get(CategoryCollection::class); @@ -427,14 +428,13 @@ public function testCategoryImageName() $categories = $response['categories']; $this->assertArrayNotHasKey('errors', $response); $this->assertNotEmpty($response['categories']['items']); - $expectedImageUrl = str_replace('index.php/', '', $expectedImageUrl); - $categories['items'][0]['image'] = str_replace('index.php/', '', $categories['items'][0]['image']); $this->assertEquals('Parent Image Category', $categories['items'][0]['name']); $this->assertEquals($expectedImageUrl, $categories['items'][0]['image']); } /** * @magentoApiDataFixture Magento/Catalog/_files/categories.php + * @magentoConfigFixture default_store web/seo/use_rewrites 1 */ public function testFilterByUrlPathTopLevelCategory() { From 9094403c198214c1dcc34021e0d4bac3bc8b091e Mon Sep 17 00:00:00 2001 From: Cari Spruiell <spruiell@adobe.com> Date: Thu, 29 Oct 2020 16:00:52 -0500 Subject: [PATCH 55/59] MC-37726: Price filter uses base currency for ranges --- app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php index cddb95d5ba765..cc76855cc6d20 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Aggregations.php @@ -37,8 +37,8 @@ class Aggregations implements ResolverInterface /** * @param \Magento\CatalogGraphQl\Model\Resolver\Layer\DataProvider\Filters $filtersDataProvider - * @param PriceCurrency $priceCurrency * @param LayerBuilder $layerBuilder + * @param PriceCurrency $priceCurrency */ public function __construct( \Magento\CatalogGraphQl\Model\Resolver\Layer\DataProvider\Filters $filtersDataProvider, From 320aee986572290d5a6f4c5324fd2d9cbf12af5c Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 30 Oct 2020 10:08:58 +0200 Subject: [PATCH 56/59] MC-38589: [MFTF] AdminEnhancedMediaGalleryVerifyAssetFilterTest failed because of bad design --- .../AdminMediaGalleryClickAddSelectedActionGroup.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml index 711a271c9d4ec..6cfc7b07831d0 100644 --- a/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml +++ b/app/code/Magento/MediaGalleryUi/Test/Mftf/ActionGroup/AdminMediaGalleryClickAddSelectedActionGroup.xml @@ -12,6 +12,6 @@ <waitForElementVisible selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="waitForAddSelectedButton"/> <click selector="{{AdminMediaGalleryHeaderButtonsSection.addSelected}}" stepKey="ClickAddSelected"/> <waitForPageLoad stepKey="waitForImageToBeAdded"/> - <waitForElementVisible selector="{{MediaGallerySection.insertEditImageModalWindow}}" stepKey="waitForLoadingMaskDisappear"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskDisappear"/> </actionGroup> </actionGroups> From 2be562a6502015f13de5829b940e7a48e0fc919c Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 30 Oct 2020 12:04:09 +0200 Subject: [PATCH 57/59] MC-33288: [2.4][MSI][MFTF] StorefrontLoggedInCustomerCreateOrderAllOptionQuantityConfigurableProductCustomStockTest fails because of bad design --- .../Catalog/Model/ResourceModel/Product/Relation.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php index 2f8c4a34f0087..392a4aeedfeb3 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Relation.php @@ -5,6 +5,7 @@ */ namespace Magento\Catalog\Model\ResourceModel\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; use Magento\Framework\Model\ResourceModel\Db\Context; use Magento\Framework\EntityManager\MetadataPool; @@ -24,16 +25,16 @@ class Relation extends AbstractDb /** * @param Context $context - * @param null $connectionName + * @param string $connectionName * @param MetadataPool $metadataPool */ public function __construct( Context $context, $connectionName = null, - MetadataPool $metadataPool + MetadataPool $metadataPool = null ) { parent::__construct($context, $connectionName); - $this->metadataPool = $metadataPool; + $this->metadataPool = $metadataPool ?: ObjectManager::getInstance()->get(MetadataPool::class); } /** From d180f78d5ebc04c43ef76f466843a7cb9b123570 Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Fri, 30 Oct 2020 14:04:16 +0200 Subject: [PATCH 58/59] MC-38814: [MFTF] AdminMediaGalleryInsertLargeImageFileSizeTest failed because of bad design --- ...diaGalleryInsertImageLargeFileSizeTest.xml | 58 +++++++++++++++++++ ...diaGalleryInsertLargeImageFileSizeTest.xml | 7 ++- 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertImageLargeFileSizeTest.xml diff --git a/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertImageLargeFileSizeTest.xml b/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertImageLargeFileSizeTest.xml new file mode 100644 index 0000000000000..2d80b490e2d9b --- /dev/null +++ b/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertImageLargeFileSizeTest.xml @@ -0,0 +1,58 @@ +<?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="AdminMediaGalleryInsertImageLargeFileSizeTest"> + <annotations> + <features value="MediaGalleryRenditions"/> + <stories value="User inserts image rendition to the content"/> + <title value="Admin user should see correct image file size after rendition"/> + <description value="Admin user should see correct image file size after rendition"/> + <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1507933/scenarios/5200023"/> + <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1806"/> + <severity value="AVERAGE"/> + <group value="media_gallery_ui"/> + </annotations> + + <before> + <createData entity="SimpleSubCategory" stepKey="category"/> + <actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> + </before> + + <after> + <deleteData createDataKey="category" stepKey="deleteCategory"/> + <actionGroup ref="AdminEnhancedMediaGalleryDeletedAllImagesActionGroup" stepKey="deleteAllImages"/> + <actionGroup ref="AdminOpenCategoryGridPageActionGroup" stepKey="openMediaGalleryCategoryGridPage"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFilters"/> + <actionGroup ref="AdminLogoutActionGroup" stepKey="logoutFromAdmin"/> + </after> + + <!-- Open category page --> + <actionGroup ref="GoToAdminCategoryPageByIdActionGroup" stepKey="openCategoryPage"> + <argument name="id" value="$category.id$"/> + </actionGroup> + + <!-- Add image to category from gallery --> + <actionGroup ref="AdminOpenMediaGalleryFromCategoryImageUploaderActionGroup" stepKey="openMediaGallery"/> + <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearGridFiltersAgain"/> + <actionGroup ref="AdminEnhancedMediaGalleryUploadImageActionGroup" stepKey="addCategoryImage"> + <argument name="image" value="ImageUpload"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickImageInGridActionGroup" stepKey="selectImage"> + <argument name="imageName" value="{{ImageUpload.fileName}}"/> + </actionGroup> + <actionGroup ref="AdminMediaGalleryClickAddSelectedActionGroup" stepKey="addSelected"/> + + <!-- Assert added image size --> + <actionGroup ref="AdminAssertImageUploadFileSizeThanActionGroup" stepKey="assertSize"> + <argument name="fileSize" value="26 KB"/> + </actionGroup> + </test> +</tests> diff --git a/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertLargeImageFileSizeTest.xml b/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertLargeImageFileSizeTest.xml index d859f4852aaaf..061f062eabe6b 100644 --- a/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertLargeImageFileSizeTest.xml +++ b/app/code/Magento/MediaGalleryRenditions/Test/Mftf/Test/AdminMediaGalleryInsertLargeImageFileSizeTest.xml @@ -8,16 +8,19 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="AdminMediaGalleryInsertLargeImageFileSizeTest"> + <test name="AdminMediaGalleryInsertLargeImageFileSizeTest" deprecated="Use AdminMediaGalleryInsertImageLargeFileSizeTest instead"> <annotations> <features value="AdminMediaGalleryInsertLargeImageFileSizeTest"/> <useCaseId value="https://github.com/magento/adobe-stock-integration/issues/1806"/> - <title value="Admin user should see correct image file size after rendition"/> + <title value="DEPRECATED. Admin user should see correct image file size after rendition"/> <testCaseId value="https://studio.cucumber.io/projects/131313/test-plan/folders/1507933/scenarios/5200023"/> <stories value="User inserts image rendition to the content"/> <description value="Admin user should see correct image file size after rendition"/> <severity value="AVERAGE"/> <group value="media_gallery_ui"/> + <skip> + <issueId value="DEPRECATED">Use AdminMediaGalleryInsertImageLargeFileSizeTest instead</issueId> + </skip> </annotations> <before> <createData entity="SimpleSubCategory" stepKey="category"/> From 5fe07d4224a809791e6cb64903d5024ca944b07a Mon Sep 17 00:00:00 2001 From: Myroslav Dobra <dmaraptor@gmail.com> Date: Mon, 2 Nov 2020 17:09:14 +0200 Subject: [PATCH 59/59] MC-38651: [MFTF] AdminMediaGalleryAssertUsedInLinkPagesGridTest failed because of bad design --- .../Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml index 539d6ccb6c0dd..4e589faef9a1f 100644 --- a/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml +++ b/app/code/Magento/MediaGalleryCmsUi/Test/Mftf/Test/AdminMediaGalleryAssertUsedInLinkedPagesGridTest.xml @@ -60,8 +60,8 @@ <actionGroup ref="AdminAssertMediaGalleryFilterPlaceHolderGridActionGroup" stepKey="assertFilterApplied"> <argument name="filterPlaceholder" value="{{ImageMetadata.title}}"/> </actionGroup> - <actionGroup ref="AdminDeleteCmsPageFromGridActionGroup" stepKey="deleteCmsPage"> - <argument name="urlKey" value="{{_defaultCmsPage.identifier}}"/> + <actionGroup ref="AdminDeleteCMSPageByUrlKeyActionGroup" stepKey="deleteCmsPage"> + <argument name="pageUrlKey" value="{{_defaultCmsPage.identifier}}"/> </actionGroup> <actionGroup ref="ClearFiltersAdminDataGridActionGroup" stepKey="clearFiltersInPageGrid"/>